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
/
BYE5
/
BYE520.LBR
/
BYE520.AZM
/
BYE520.ASM
Wrap
Assembly Source File
|
2000-06-30
|
162KB
|
6,622 lines
; BYE520 - REMOTE CONSOLE PROGRAM FOR CP/M AND MODEM - 01/20/89
;
; For use with CP/M 2 or CP/M 3
;
;
; NOTE: Read the BYE5.HIS in this .LBR to review
; update history and to see changes imple-
; mented by this version.
;
;
; BYE5 replaces all previous BYE2, BYE3, BYE4, BYE+, and MBYE series and
; also supports the latest available technology for RCP/M systems. BYE5
; will work with KMD04 and XMODEM-116 or later revisions.
;
;=======================================================================
;
; NOTE: This program is copyrighted (c) 1986 by Wayne Masters, Irv Hoff,
; and George Peace. All rights reserved. Users are hereby granted
; a limited license to copy this program for personal use only. The
; program may be distributed unmodified to all interested parties.
; No fee or other consideration shall be accepted by any party or
; parties. In accordance with the copyright law of 1978, form TX
; has been sent to the U.S. Government Copyright Office.
;
; TABBY changes incorportated by Marc Newman, The Black Box DRBBS/TABBY
; 713-480-2686 BBS, FIDONET node 1:106/601 on 1/17/89. Many thanks to
; George, Irv and Wayne, Jack Winslade, and Philip Hansford for all the
; help and encouragement.
; = = = = = = = =
;
; If you have changes that you would like to see in a forthcoming
; general release, please forward them for consideration. This
; seems to be the only way to control the modifications that have
; run rampant in previous versions of public domain programs. It
; has taken many hours to correct problems some of these changes
; have caused, particularly when used with assemblers that have
; characteristics different from the one being currently used or
; if other equates are selected.
;
; Send/call any suggestions or requests for help to:
;
; Wayne Masters Irv Hoff, W6FFC George Peace
; (408) 378-3798 voice (415) 948-2166 voice (717) 657-0285 voice
;
; Potpourri RCPM CP/M-3 George Peace
; (408) 378-7474 (717) 657-8699
;
; = = = = = = = =
;
; If using M80, remove the ";" at the beginning of the ASEG line.
;
; ASEG ; Needed for M80, but RMAC can't handle it
;
; This program allows modem callers to use a CP/M system just as if they
; were seated at the system console. Special assembly-time options al-
; low limiting the caller's access by password and/or access to only a
; message-service program. A number of external inserts are available
; to adapt this program to various computers, clocks and modems. It
; may be assembled with ASM, LASM, MAC, RMAC, SLRMAC or M80. If the
; ZCPR3 equate is YES, a macro assembler such as MAC, M80 or SLRMAC
; will be required. If the program will not assemble correctly with
; M80, check the insert that was added, it likely is not configured
; properly.
;
; BYE5 will continue supporting what the Sysop's organizations have re-
; quested, not personal preferences.
; - Wayne Masters
;
;=======================================================================
;
; The following files are inside this library to assist you in installa-
; tion:
;
; BYE5.DOC For general installation and extended BDOS functions
; B5-CPM3.DOC Specific instructions for CP/M 3 installation
; BYE5.HIS BYE5 update history (read this to see latest features)
; BYE5-INS.INF Computer-specific inserts currently available (CP/M 2 & 3)
; B5-TIME.INF Clock inserts currently available (CP/M 2 & 3)
; B5IM-1.DOC Intelligent (smart) modem configuration information
; BYE5nnC.AQM Condensed version of BYE5 for small floppy based systems
;
;=======================================================================
;
; If the CPM3 equate is YES, BYE5 uses an RSX loader to attach itself to
; your operating system (see B5-CPM3.DOC). For CP/M-2 users, (CPM3 NO),
; BYE5 uses a special loader that is built into the program to automati-
; cally move itself below CCP. This does not require any alteration in
; the location of CP/M by using MOVECPM. All you need to do is: (1)
; choose the desired options, (2) patch in the insert for your computer
; in the special area near the start marked "+++ Install your I/O port
; insert here +++", (3) patch in the insert for your clock at label TIME
; (if CLOCK is YES), (4) then finish editing, assemble, load and use.
;
; Most users of this program will have a modem such as an Anchor, Hayes,
; ProModem, U.S.Robotics, or Racal Vadic Maxwell. All these types are
; "intelligent" modems. If using this type of modem, set the IMODEM
; and B5IM equates to 'YES'. Otherwise leave them set to 'NO' and BYE
; assumes you have a "dumb" auto-answer modem, (such as a Bell 212A).
; This readily adapts the program to a wide variety of modems and I/O
; serial types.
;
; NOTE: Two support libraries exist for BYE5...
; BYE5-INS.LBR contains all available computer-specific inserts
; B5-CLOCK.LBR contains all available clock inserts.
;
; Be sure to check Potpourri for the latest version of these inserts.
; Many have been corrected and/or updated by users of BYE5 and the one(s)
; you have may not be the latest version.
;
; The program does the following:
;
; If you type BYE E, BYE will load and execute as though it has
; a valid carrier or caller. Handy for debug, else it:
;
; 1) Hangs up the phone
; 2) Awaits ring if B5IM is YES, (or carrier detect if B5IM is NO)
; allows exit to CP/M if local KEYB types CTL-C
; 3) Answers the phone and outputs carrier
; 4) Awaits incoming carrier. If none found in 30 seconds goes
; back to step 1
; 5) Detects the speed of caller and sets local cpu to that speed
; 6) Asks number of nulls (0-9) (optional)
; 7) Sets the log-in time (if TIMEON is YES)
; 8) Types the "WELCOME" file from disk, (optional) allowing
; CTL-C to skip it
; 9) Asks for a password (optional), allowing 3 tries to get
; it right. When entered drops into CP/M
; 10) Caller can leave by hanging up, (any time carrier is
; lost, it waits then goes back to step 1) or the caller
; may type the program name (BYE).
; - Notes by Wayne Masters
;
;=======================================================================
;
MAIN EQU 5
VERS EQU 20
MONTH EQU 01
DAY EQU 20
YEAR EQU 89
;
;
; System equates
;
NO EQU 0
YES EQU NOT NO ; For conditional assembly
;
;
; You will likely also want to change the password, located below at
; label 'PASSWD' (if you set PWRQD YES). If you are using a BBS .COM
; file then PWRQD is normally left NO.
;
;***********************************************************************
;
; OPTION CONFIGURATION SECTION
;
;***********************************************************************
;
;-----------------------------------------------------------------------
; BYE5 configuration
;
;
LOCMD EQU 61 ; BYE's lowest extended BDOS call
HICMD EQU LOCMD+28 ; BYE's highest extended BDOS call
CCPL EQU 8 ; Number of sectors for CCP size (norm
; Is 8. Apples with Micrsoft CP/M
; V2.23+ use 9. Systems w/Trantor WL
; BIOS, set to 0 and set TRANWL YES.
; For older versions of Trantor BIOS
; Start with 24 and work down until it
; Stops working (typically 24 or 16).
; An updated Trantor (WL) BIOS is ad-
; Vised for RCP/M use if running a
; Large BBS program. CP/M-3 does not
; Use this or TRANWL equates.
;
;-----------------------------------------------------------------------
; COMPUTER TYPE
;
ATR EQU NO ; MEANS KAYPRO
;
;-----------------------------------------------------------------------
; Modem Type
;
IMODEM EQU NO ; Yes, for intelligent modem, including
; Hayes
B5IM EQU NO ; Yes, your modem uses AT protocol, like
; Hayes
;
;
; Set one (and only one) of the following HS equates to YES
;
HS9600 EQU NO ; Yes, if modem's high speed is 9600 bps
HS4800 EQU NO ; Yes, if modem's high speed is 4800 bps
HS2400 EQU NO ; Yes, if modem's high speed is 2400 bps
HS1200 EQU Yes ; Yes, if modem's high speed is 1200 bps
HS300 EQU NO ; Yes, if modem's high speed is 300 bps
;
;
; The next 7 equates are only used if B5IM is YES
;
DOATZ EQU NO ; Yes to do ATZ between calls. If your
; Modem reverts to auto-answer after
; ATZ, set this NO. It speeds up the
; Turnaround between calls AND pre-
; Vents modem from answering while
; BYE5 is trying to reinitialize for
; The next call. Most modems (Hayes
; And clones) don't need it
ECHO EQU NO ; Yes for Hayes, ProModem, Courier, RV-
; Maxwell, NO for all others (USR,
; Anchor, etc.)
ANCHOR EQU NO ; Yes, if you have a Mark XII
NODTR EQU NO ; Yes, modem or computer does not sup-
; Port DTR such as Anchor Mark XII or
; Some Osborne-1's. NOTE OS-1 users..
; BYE5 can handle your NODTR problem,
; But will NOT work unless you install
; The hardware mod to fix the carrier
; Detect logic. The same mod also
; Fixes the DTR problem, so you should
; Install the whole mother board modi-
; Fication kit and set this NO
NOATA EQU NO ; Yes, if you have an older Password,
; 212A or S-100 that will not execute
; The ATA command after ring is de-
; Tected. Newer firmware works.
OFFHK EQU NO ; Yes, if you want BYE to put your phone
; Off-hook (ATH1) when running locally
; (E) or exiting to CP/M (instead of
; Using ATS0=0)
SHORTB EQU NO ; Yes, for modems that that can't accept
; A 30 character CMD string, like the
; MultiModem.
;
;-----------------------------------------------------------------------
; General Equates
;
HARDLOG EQU NO ; Yes, echo remote input to printer
PRINTER EQU NO ; Yes, if your bbs uses printer for er-
; Ror msgs. or if you use ^P remotely.
; QBBS users say YES if QENTER is set
; To print callers data
; NOTE, if you use your printer I/O drivers
; For your modem, then say YES to this
COMFILE EQU Yes ; Yes, chain to a .COM file on carrier
; Detect
COMDRV EQU 'A' ; Drive to look for .COM file on
COMUSR EQU 0 ; User# of .COM file to be called after
; Answer
DISKLOG EQU NO ; Yes, echo remote input to disk file
; Warning..this code requires appx 1024 bytes
; Large BBS programs may not work on cp/m 2.2
; if you use this.
LOGUSR EQU 15 ; User number of SYS.LOG file
LOGDRV EQU 'A' ; Drive for SYS.LOG file
;
EXFILE EQU NO ; Yes, chain to a .COM file when BYE
; Logs off a caller (even when he
; Types BYE). Your exit.COM file must
; Preserve the stack and do a RETURN
; (not warmboot) to re-enter BYE cor-
; Rectly or use the EXRET method below
; CPM3 or PBBS users must say YES to this
; QBBS users must say NO, MBBS NO if CP/M 2
; MBBS YES if using CPM3. DRBBS says no.
;
EXRET EQU no ; YES, if your exit file can't preserve the
; Stack and do a normal RETURN. MBASIC,
; "C", and some Pascal programs can't do
; The stack save-return easily. Simply
; POKE FCB+1 (5DH) with 'r' (small r) and
; Do a warmboot (SYSTEM) and BYE5 will
; Handle your exit file return correctly
BYHANG EQU NO ; Yes, for BYE5 to say goodbye and hangup
; The phone BEFORE calling your EXIT file
; METAL, & OxGate users must say YES
; PBBS v2.n YES, PBBS 3.0 or > NO
; PBBS v2.n must change EXITFCB to BYE.COM
; Instead of PBYE.COM. DRBBS says YES
EXDRV EQU 'A' ; Drive to look for exit .COM file on
EXUSR EQU 0 ; User # of .COM file to be called upon
; Exit
MSGFIL EQU no ; Yes, if your BBS system allows mes-
; Sages to be uploaded by KMD11 and
; Later with the RM option. KMD11
; Sets a flag that will cause your
; MSG.COM file to be executed. The
; COM file must be on the same D/U
; As COMFILE. Your MSG.COM file can
; Append (then erase) the uploaded
; Message(s) to your message file.w
; Your MSG.COM file must preserve the
; Stack and do a RETURN (not warmboot)
; To renter BYE. You can select the
; Name of MSG.COM at label MSGFCB:
; (default name is MFMSG.COM)
NO25TH EQU Yes ; Yes, you wish to display LASTCALR data
; (^W). You may also print a header
; Above the LC data. Put your custom-
; Ized header at label LCHEAD:
; MBBS, PBBS, QBBS users must say YES
NO25BF EQU 78 ; Size (bytes) of lc buffer needed by
; Your BBS. MBBS, QBBS = 65
; METAL, PBBS, OXGATE =78
READLC EQU yes ; Yes, to have BYE read your LASTCALR
; File, No if your BBS pokes LASTCALR
; Into BYE. MBBS, PBBS, QBBS, METAL,
; And OxGate users say NO. DRBBS says yes
LCDRV EQU 'A' ; Drive to find LASTCALR or LASTCALR.DAT
LCUSR EQU 0 ; User # of LASTCALR or LASTCALR.DAT file
;
SKTERM EQU YES ; Yes, to skip the code that waits for the
; Caller to get his modem program into
; Terminal mode. Caution...The caller may
; Miss your opening welcome text if you set
; This equate yes. If your BBS program
; Has code built in to make sure the caller
; Is ready AND in terminal mode, set to yes
;
TABBY EQU YES ; If you are running TABBY, and want RECMAIL
; to be run upon receipt of a TSYNC, set this.
TSYNC EQU 0AEH ; TSYNC character for TABBY
ESC EQU 01BH ; Escape character for TABBY
TABCNT EQU 150 ; Wait about 15 seconds
NNHOUR EQU 3 ; Define your National Netmail Hour here
TBYUSER EQU 0 ; User area for Tabby DISPATCH.COM
TBYDRV EQU 'A' ; Drive for Tabby DISPATCH.COm
;
WBDRIV EQU 'A'-41H ; Drive to log to on first warmboot to cp/m
; Some add-on hard disk systems want C
;
WELFILE EQU NO ; Yes, to send a WELCOME file
WELDRV EQU 'A' ; Drive to look for WELCOME??? file
WELUSR EQU 14 ; User number of WELCOME??? file
;
CLRSCR EQU NO ; Yes, to auto-clear local CRT screen
; Between calls. No, will still allow
; You to use ^Z to manually clear it.
; You are allowed a 6 byte sequence
; Below. The example is for an <ESC>:
; If you use a ctrl-key (example, ^Z),
; Set CLRCH1 EQU 'Z'-40H. Set all
; Unused bytes 0. Leave this NO until
; Everything is working
CLRCH1 EQU 1BH ; Set these for your clear screen sequence
CLRCH2 EQU '*' ; 1B is escape and ESC * clears my screen
CLRCH3 EQU 0 ; (Byte 3 if you need it).
CLRCH4 EQU 0 ; Six bytes allowed for clear screen
CLRCH5 EQU 0 ; Sequence and you can also clear your
CLRCH6 EQU 0 ; 25th line if desired.
;
PRGRSS EQU NO ; Yes, for helpful progress reports on
; CRT. Leave this YES until every-
; Thing is working
PRNTGB EQU NO ; Yes, print "Goodbye..." message
PRNTWB EQU NO ; Yes, print a string for each warm boot
PWRQD EQU NO ; Yes, password needed for CP/M access
RVIDEO EQU NO ; Yes, display local messages in reverse
; Video when caller is online. (Set your
; On/off sequence below). This also works
; With half intensity instead of reverse v.
RVON1 EQU 1BH ; Set your reverse-on sequence in these 4
RVON2 EQU 0b0h ; Bytes. Set unused bytes to nulls (0).
RVON3 EQU 0 ; 1BH is escape, ESC G4 is reverse video
RVON4 EQU 0 ; ON for the Televideo 925 terminal
;
RVOFF1 EQU 1BH ; Now set the reverse-off sequence as above
RVOFF2 EQU 0c0h ; ESC G0 is reverse video OFF for the 925
RVOFF3 EQU 0
RVOFF4 EQU 0 ; Set unused bytes to 0
;
TOVALUE EQU 5 ; Minutes of no-activity allowed. 255 max.
;
;-----------------------------------------------------------------------
; System and Hardware dependent options
;
CPM3 EQU NO ; Yes, installing with CP/M 3.0, see
; B5-CPM3.DOC
;
;
; The next six equates are only for CPM3 users
;
CCPPLUS EQU NO ; Yes, CCP+ installed.
;
HISTRSX EQU NO ; Yes, clear command line HISTory if
; HIST+ RSX is installed
SDRV1 EQU 1 ; Set these 4 equates to the default
SDRV2 EQU 0FFH ; Drive search chain.
SDRV3 EQU 0FFH ; 0 = current, 0FFH = end of chain.
SDRV4 EQU 0FFH ; 1 = A, 2 = B, etc.
;
; End of CPM3 only
;
CLOSS EQU 1 ; If carrier dies, wait 1 second, then
; Hang up
CTRLC EQU 'K'-'@' ; Map ^C to this character
DOWNMIN EQU 5 ; Number of min after Sysop types ^O to
; Logout
LOSER EQU NO ; Yes, warm boot overwrites part of the
; BIOS
MHZ EQU 4 ; Processor clock in MHz
MOTOR EQU NO ; Yes power up/down drives between calls
TRANWL EQU NO ; Yes if running Trantor WL BIOS system
;
;-----------------------------------------------------------------------
; Filtered characters
; BYE5 filters incoming modem noise by ignoring those characters most
; frequently generated by noisy modems or marginal phone connections.
; Also, some incoming characters may cause your local terminal to do
; strange (and sometimes undocumented) things. The most common char-
; acters generated by noisy modem connections are the left brace ({),
; the delete character (07F) and nulls (00H). An example of problem
; characters for the TRS-80 is the backward slash (\). You may select
; any 4 characters below for BYE5 to filter from the incoming modem.
; Set any, or all, to nulls (00H) if you choose not to use the modem
; filter code.
;
FILT1 EQU 7BH ; Left brace
FILT2 EQU 7FH ; Delete character
FILT3 EQU 60H ; Backward slash (TRS-80 problem)
FILT4 EQU 00H ; Null
;
;-----------------------------------------------------------------------
; Function Keys
;
LEADIN EQU YES ; Yes, to use lead-in character for
; F-keys instead of single CTL chars.
;
IF LEADIN
LEADKY EQU '\' ; Key to use for lead-in. Choose a sel-
; Dom used key.
ENDIF ; LEADIN
;
;
; If LEADIN is YES, you must type the LEADKY first, then the character
; inside the ' ' below. If LEADIN is NO, the following characters are
; used as a single control key. Select only your character preference
; inside the ' ', and leave the -40H alone. Either option will accept
; upper and lower case.
;
ANSKEY EQU 'A'-40H ; Key to force modem to answer the phone
BLNKKEY EQU 'B'-40H ; Key to toggle remote terminal on/off
LOGKEY EQU 'D'-40H ; Key to flip disk log file save.
BELLKEY EQU 'G'-40H ; Key to toggle bells on console
LCKEY EQU 'L'-40H ; Key to force return to local cp/m after
; Current caller logs off (& alert sysop)
TWITKEY EQU 'N'-40H ; Keycode to hangup modem manually
SYSDKEY EQU 'O'-40H ; Key to print "System going down in
; N min.."
MSGKEY EQU 'Q'-40H ; Keycode to print "Message from SYSOP:"
TIMEKEY EQU 'T'-40H ; Key for Sysop to display time (if
; TIMEON)
ULTKEY EQU 'U'-40H ; Key to grant current caller unlimited
; Time. Also enables all the flag bits
; In LCPTR
WHOKEY EQU 'W'-40H ; Key to display LASTCALR if NO25TH is
; YES
XITKEY EQU 'X'-40H ; Key to exit from "Message from Sysop"
; Loop
ZCREEN EQU 'Z'-40H ; Key to manually clear your screen
;
;-----------------------------------------------------------------------
; RBBS Type
;
; Set only one, or none of the following BBS equates to YES. If COMFILE
; YES and none of the below are selected you will have an undefined label
; COMFCB during assembly.
;
METAL EQU NO ; Yes, running METAL BBS system.
;
MBBS EQU NO ; Yes, running MBBS4n BBS system
MBSDRV EQU 'A' ; Drive where you keep MBBS.COM
MBSUSR EQU 0 ; User area for MBBS.COM
; LOGIN.COM and MFGMSG.COM must both be on
; COMDRV and COMUSR selected above
;
MINICK EQU YES ; Yes, running MINICBBS..you must also create
; Your COMFCB label
;
OXGATE EQU NO ; Yes, running OxGate BBS system
PBBS EQU NO ; Yes, running PBBS system
QBBS EQU NO ; Yes, running QBBS system
RBBS EQU NO ; Yes, running RBBS, sets/resets
; 'WRTLOC' flag
DRBBS EQU YES ; Yes, running DRBBS
IOVAL EQU 1 ; Initial value for IOBYTE (if MINICK
; YES)
LMBELL EQU NO ; Yes, your bbs uses a low-memory bell flag
; MBBS and RBBS users must say YES
KILBEL EQU 03BH ; Byte for low memory bell toggle flag
;
;
; Some BBS systems require a flag to be reset to allow reentry to the
; BBS from CP/M (older versions of RBBS do). If you run a BBS that uses
; this technique, then set RTOK to YES, and define the byte to reset at
; RTOKFG. BYE5 will reset this byte to zero between calls.
;
RTOK EQU YES ; Yes, to reset the following byte be-
RTOKFG EQU 020H ; Tween calls. PBBS users should say
; Yes, and set RTOKFG EQU to your REENTR
; Byte, normally 20H.
;
;-----------------------------------------------------------------------
; Clock/Time Equates
;
; NOTE... Be sure to set the CLOCK and TIMEON equates the same way in
; both BYE5 and KMD.
;
CLOCK EQU YES ; If YES, add your clock reader code at
; The start of label TIME: and store
; Binary values in CCHOUR and CCMIN
; PBBS and QBBS users must say YES
BCD2BIN EQU YES ; Yes, your clock routine calls BCDBIN
BIN2BCD EQU YES ; Yes, your clock routine calls BINBCD
TIMEON EQU YES ; Yes, if you want BYE5 to keep track of
; Time-on-system and log off user
; After MAXMIN. This works without a
; Clock if you use KMD
MAXMIN EQU 60 ; Minutes for maximum time allowed on
; System. Recommend 60 if CLOCK and
; TIMEON are YES, and 45 if CLOCK is
; NO and TIMEON YES. (255 minutes
; Maximum). 0= No restrictions.
CLKDSP EQU no ; Do you want a real time clock displayed?
;
; NOTE, the previous callers timeon is preserved for your exit or login
; program to access in BYE's fixed lookup table at label LCPTR. You may
; choose to store that data in low memory, or elsewhere by changing the
; LCTON equate to a new address. LCTON is found just after BYE's fixed
; lookup table.
;
PRNTOS EQU NO ; Yes, print Time-left-on-system on warmboots
; If WHEEL is on or MXTIME=0, this will print
; Time-on-system rather than Time-left...
RSPEED EQU NO ; Yes, if you want to limit speeds during
; prime time
; Speed (a clock read routine is re-
; Quired if YES - see CLOCK)
;
IF RSPEED ; 24 hour clock, 00=midnight, 23=11PM
HOUR1 EQU 19 ; Start of prime-time (19=7:00 PM)
HOUR2 EQU 23 ; End of prime-time (23=11:00 PM)
SPEED EQU 5 ; Minimum speed accepted (5=1200 baud).
; Change OFFMSG to match your times,
; Baud rate and time zone. OFFMSG is
; A message at code end.
ENDIF ; RSPEED
;
;-----------------------------------------------------------------------
; CCP Options
;
ZCPR2 EQU Yes ; Yes, if running ZCPR1/2, ZCMD1/2 or
; NZCPR1/2
; Yes, if using CP/M 3 with wheel byte
ZCPR3 EQU NO ; Yes, if running ZCPR3
;
;
; NOTE: requires MAC.COM to assemble if ZCPR3 set YES
;
IF ZCPR3
MACLIB Z3BASE ; Requires MAC to assemble...otherwise
; Enter constants directly..see label
; DOZ3 for required EQU's
ENDIF ; ZCPR3
;
;
; NZCPR/ZCMD/ZCPR all use bytes (at 3DH/3EH/3FH) to store the maximum
; drive, wheel status, and maximum user area. Some BBS systems poke
; these low memory bytes to reset these (for Sysop, etc.) Other BBS
; systems (like OxGate) poke the bytes in BYE that do the same thing.
; The equate USEZCPR allows you to select where you want to poke things.
; For OxGate, set it to NO, for RBBS, you probably want it set to YES.
; If you are NOT using NZCPR/ZCMD/ZCPR then set USEZCPR to NO.
;
USEZCPR EQU NO ; Yes, if using ZCPR/NZCPR/ZCMD to set
; Bytes
CHEKDU EQU NO ; Yes, if you want BYE to police MAXDRIV
; And MAXUSER. No, if your CCP can do
; That (saves a lot of code). In
; Either case, BYE keeps correct
; Values in these low memory bytes
MAXDRIV EQU 003DH ; ZCPR lolcation of MAXDRIV byte
WHEEL EQU 003EH ; Location of ZCPR's wheel flag
MAXUSER EQU 003FH ; ZCPR location of MAXUSR byte
MAXDRV EQU 'B'-'@' ; Highest drive supported
MAXUSR EQU 14 ; Highest user area
SYSDRV EQU 'C'-'@' ; Highest local drive supported
SYSUSR EQU 15 ; Highest local user area (0-15)
;
;
; If CHGPATH is YES, BYE automagically will change the .COM path to suit
; which mode it is in. An example of this is: when remote, the path is
; $$:, A0: -- when local, MY path is $$:, A0:, A15: which allows keeping
; PIP and FORMAT and other nasties up in A15: -- See REMPATH and SYSPATH
; DB's at end of program for current paths. If the Sysop uses the ^B to
; blank the remote console, the Wheel byte is set and SYSPATH is setup
; for the Sysop. The wheel byte is reset and REMPATH setup when ^B is
; used the second time to turn the remote back on.
;
CHGPATH EQU NO ; Yes, if changing ZCPR's external path
EXTPATH EQU 0040H ; ZCPR external path default location
;
;-----------------------------------------------------------------------
; MSPEED values
;
MSPEED EQU 03CH ; Baud rate pointer
BP110 EQU 0 ; 110 baud - baud rate pntrs for MSPEED
BP300 EQU 1 ; 300 baud
BP450 EQU 2 ; 450 baud
BP600 EQU 3 ; 600 baud
BP710 EQU 4 ; 710 baud
BP1200 EQU 5 ; 1200 baud
BP2400 EQU 6 ; 2400 baud
BP4800 EQU 7 ; 4800 baud
BP9600 EQU 8 ; 9600 baud
BP19200 EQU 9 ; 19200 baud
;
;-----------------------------------------------------------------------
; Motor controlled drives
;
; These values suit a Compupro/Viasyn Disk1A with YE-DATA 180 20cm
; drives. Alter to suit your needs if your disk controller supports
; motor control.
;
IF MOTOR
DISK EQU 0C3H ; Disk control port
DISKON EQU 080H ; Motors on
DISKOFF EQU 000H ; Motors off
ENDIF ; MOTOR
;
;-----------------------------------------------------------------------
; if using LOSER
;
; There are some cases where warm boot overwrites the initial BIOS jump
; table. This problem was solved for the Superbrain 3.0 bios by find-
; ing a warmboot call to HIGH in the BIOS. This call is then patched by
; BYE. The form of the call is: WBCALL CALL WMSTRT
;
IF LOSER
WBCALL EQU 0E260H ; Check this in your BIOS
;
;
; The following location is called
;
WMSTRT EQU 0E566H ; Check this in your BIOS
ENDIF ; LOSER
;
;-----------------------------------------------------------------------
;
; END OF OPTION CONFIGURATION SECTION FOR BYE5
;
;-----------------------------------------------------------------------
;
IF NOT CPM3
ORG 100H
;
;-------------------- Special Loader Routine ---------------------------
;
START: LXI SP,ISTACK ; Set stack for initialization routine
MVI C,32
MVI E,241
CALL BDOS ; See if BYE is running
CPI 77 ; Yes, if (A)=77
JNZ STARTA ; No, we must relocate code
;
;
; Ok, we're sure that BYE's already there
;
LHLD BDOS+1 ; Load BDOS vector
INX H ; Compute start of BYE5
INX H
INX H
PCHL ; Go execute already loaded code
ENDIF ; NOT CPM3
;
STARTA: IF COMFILE AND (NOT CPM3)
LXI H,COMFCB+1 ; BBS com filename
LXI D,ENTMSG ; Display buffer
MVI B,8 ; Length of filename
;
STAR1: MOV A,M ; Move it to display buffer
CPI ' ' ; Stop on first space
JZ STAR2
STAX D
INX D
INX H
DCR B
JNZ STAR1 ; Loop until space or 8 chars found
;
STAR2: XRA A
STAX D ; Store 0 as print terminator
ENDIF ; COMFILE AND NOT CPM3
;
IF EXFILE AND (NOT CPM3)
LXI H,EXITFCB+1 ; Exit com filename
LXI D,EXTMSG ; Display buffer
MVI B,8 ; Length of filename
;
STAR3: MOV A,M ; Move it to display buffer
CPI ' ' ; Stop on first space
JZ STAR4
STAX D
INX D
INX H
DCR B
JNZ STAR3 ; Loop until space or 8 chars found
;
STAR4: XRA A
STAX D ; Store 0 as print terminator
ENDIF ; EXFILE AND NOT CPM3
;
IF MSGFIL AND (NOT CPM3)
LXI H,MSGFCB+1 ; Message com filename
LXI D,MSGMSG ; Display buffer
MVI B,8 ; Length of filename
;
STAR5: MOV A,M ; Move it to display buffer
CPI ' ' ; Stop on first space
JZ STAR6
STAX D
INX D
INX H
DCR B
JNZ STAR5 ; Loop until space or 8 chars found
;
STAR6: XRA A
STAX D ; Store 0 as print terminator
ENDIF ; MSGFIL AND NOT CPM3
;
IF LMBELL AND (NOT CPM3)
LDA BELLON
CMA
STA KILBEL ; Prep the low memory bell flag
ENDIF ; LMBELL AND NOT CPM3
;
IF NOT CPM3
LHLD BDOS+1 ; Load BDOS vector
LXI D,-(CCPL*256)-8 ; 2k btyes in CCP plus offset
DAD D ; Make room for the CCP
;
;
; HL now contains the destination address of BYE5
;
LXI D,OBJEND-1 ; Set up the source pointer
LXI B,OBJEND-BEGOBJ ; Set up byte counter
;
BLOCK: LDAX D ; Get program byte
MOV M,A ; Move program byte
MOV A,B ; Get byte count
ORA C ; Finished block transfer?
JZ UPDATE ; Yes, check on the opcode values
DCX D ; No, set source pointer
DCX H ; Set destination pointer
DCX B ; Set byte counter
JMP BLOCK ; Continue block transfer until finished
;
UPDATE: XCHG ; Move the source addrress into 'HL'
CALL NEGHL ; Prepare value for subtraction
DAD D ; Form the program offset
SHLD OFFSET ; Save the program offset
XCHG ; Set up the offset register
LXI H,ENDOBJ ; Get the ending addr of the prgm code
DAD D ; Form new ending addr (new location)
SHLD ENDRNG ; Save the ending addr of the prgm code
LXI H,BEGOBJ ; Get the start address of program code
DAD D ; Form new beginning addr (new location)
;
;
; The following code determines whether or not an address is within the
; BYE prgm and sets it to the new address if it is - otherwise it will
; not disturb the code.
;
DCX H ; Set up the source pointer for the
; Modification routine entry
MODIFY: INX H ; Point to the next (hopefully) instr.
DB LXID ; Get the address of the end of BYE5
;
ENDRNG: DW 0
MOV A,E
SUB L
MOV A,D
SBB H ; Have we finished moving this block?
JC BEGIN ; Yes, we can begin now.
;
;
; Here is where we test for the 3-byte opcodes
;
MVI B,INST3E-INST3 ; Get number of elements in the table
LXI D,INST3 ; Set up the 3-byte opcodes table ptr
;
THRBYT: LDAX D ; Get opcode byte from table
CMP M ; Is this byte a 3-byte opcode?
JZ CHANGE ; Change the 2nd and 3rd bytes if needed
INX D ; No, advance table pointer
DCR B ; End of 3-byte table?
JNZ THRBYT ; No, keep looking
;
;
; Skip all the 2-byte opcodes - this keeps the transfer program from
; trying to figure out what the second byte is.
;
MVI B,INST2E-INST2 ; Get the number of table elements
LXI D,INST2 ; Set up the 2-byte-opcodes-table ptr
;
TWOBYT: LDAX D ; Get opcode byte from table
CMP M ; Is this byte a 2-byte opcode?
JZ SKIP ; Yes, skip it and continue
DCR B ; No, end of 2-byte table?
INX D ; Advance table pointer
JNZ TWOBYT ; No, keep looking
JMP MODIFY ; Yes, a one-byte opcode, keep going
;
SKIP: INX H ; Advance object code pointers
JMP MODIFY ; Continue search
;
CHANGE: LXI D,OBJEND ; Set up end of range pointer
LXI B,BEGOBJ ; Set up beginning of range pointer
;
;
; See if the address is above the range
;
INX H ; Advance pointer to the LSB of the addr
MOV A,E
SUB M
INX H ; Advance pointer to the MSB of the addr
MOV A,D
SBB M
JC MODIFY
;
;
; See if the address is below the range
;
DCX H ; Set ptr back to the LSB of the addr
MOV A,M
SUB C
INX H ; Advance pointer to the MSB of the addr
MOV A,M
SBB B
JC MODIFY
;
;
; Update the value of this address by adding the offset to it
;
DCX H ; Set ptra back to LSB of the address
DB LXID ; Load DE with the offset value
;
OFFSET: DW 0
MOV A,M ; Get base address
ADD E ; Change LSB to new address
MOV M,A ; Update memory
INX H ; Advance pointer to the MSB of the addr
MOV A,M ; Get the MSB of the base addr
ADC D ; Change LSB to new address
MOV M,A ; Update memory
JMP MODIFY ; Take care of the next instruction
;
;
; Small subroutine to negate the contents of HL
;
NEGHL: MOV A,H
CMA
MOV H,A ; Get the complement of the MSB
MOV A,L
CMA
MOV L,A ; Get the complement of the LSBb
INX H ; Make 'HL' totally negative
RET
;.....
;
;
; Prepare to branch to the BYE5 program
;
BEGIN: LHLD BDOS+1
PUSH H
LXI D,BEGOBJ
LHLD OFFSET ; Get prgram offset
DAD D ; Form address of new BDOS address
SHLD BDOS+1 ; Update BDOS vector
ENDIF ; NOT CPM3
;
IF TRANWL AND (NOT CPM3)
PUSH H ; Find where it's at
CALL FNDWL
POP D
JC NOWL
MOV M,E
INX H
MOV M,D
;
NOWL: XCHG
ENDIF ; TRANWL AND NOT CPM3
;
IF NOT CPM3
INX H
POP D
MOV M,E
INX H
MOV M,D
INX H
PCHL ; Jump to relocated BYE5 program
ENDIF ; NOT CPM3
;
IF TRANWL AND (NOT CPM3)
HHSIG EQU 12
HSSIG EQU 14
HHSHL EQU 16
HLSHL EQU 18
HBSHL EQU 36
HDRVR EQU 22
HPCT EQU 25
PCMGR EQU 4*2
WWHSIG EQU 'W'
WWLSIG EQU 'H'
SIGWBT EQU 'B'
SIGUB EQU 'L'
SIGSD EQU 'S'
;
;
; FNDWL.......
; Input: none:
; Output:
; CY set. Trantor Universal Bios is not loaded
; CY clr. HL -> var where adrs of lowest shell has to
; be stored.
; BC -> lowest shell.
; DE is preserved.
;
FNDWL: PUSH D
;
; Scan downwards from High memory trying to find
; any WW shell.
;
LXI B,0FF06H
;
ASHELL: LXI H,HHSIG
DAD B
MOV A,M
CPI WWHSIG
JNZ NSHELL
INX H
MOV A,M
CPI WWLSIG
JZ WWLINK
;
NSHELL: DCR B
LDA 7
DCR A
CMP B
JC ASHELL
STC
POP D
RET
;.....
;
;
; Locate the Warm boot shell
;
WWLINK: LXI H,HSSIG
DAD B
MOV A,M
CPI SIGWBT
JZ WBFND
LXI H,HHSHL
DAD B
MOV C,M
INX H
MOV B,M
JMP WWLINK
;
;
; Build pointer to wb.lowestshell
;
WBFND: LXI H,HBSHL
DAD B
ORA A
;
WLEXIT: POP D
RET
ENDIF ; TRANWL AND NOT CPM3
;
;.....
;
;
IF NOT CPM3
;
; The following table defines the 3-byte load instructions used in the
; 8080 instruction set.
;
INST3: DB 001H,011H,021H,022H,02AH,031H,032H,03AH,0C2H
DB 0C3H,0C4H,0CAH,0CCH,0CDH,0D2H,0D4H,0DAH,0DCH
DB 0E2H,0E4H,0EAH,0ECH,0F2H,0F4H,0FAH,0FCH
INST3E EQU $ ; End of 3 byte op codes
;
;
; The following table is the listing of the 2-byte opcodes used in the
; 8080 instruction code set.
;
INST2: DB 006H,00EH,016H,01EH,026H,02EH,036H,03EH,0C6H
DB 0CEH,0D3H,0D6H,0DBH,0DEH,0E6H,0EEH,0F6H,0FEH
INST2E EQU $ ; End of 2 byte op codes
ENDIF ; NOT CPM3
;
; This is a Resident System Extension (RSX) intended to run under CP/M
; Plus. The RSX is called via BDOS function 60 (in register C) with
; register pair DE pointing to the RSX parameter block.
;
IF CPM3 ; Loader for CP/M 3.0
;
; RSX Prefix Structure
;
SERIAL: DB 0,0,0,0,0,0 ; Room to insert serial number
STARTX: JMP FTEST ; Beginning of program
NEXT: DB 0C3H ; Jump instruction op-code
DW 0 ; Next module in line (or BDOS)
PREV: DW 0 ; Previous module
REMOV: DB 0FFH ; Remove flag initially set
NONBNK: DB 0 ; >0 to load only in non-banked CP/M
RSXNAM: DB 'BYE5 ' ; The name of this RSX
LOADER: DB 0 ; Loader flag
DB 0,0 ; Reserved
;
;
; BDOS function 60 sub-functions used by this RSX
;
; 4 Bye test for CCP+
; 7 Return address of BYE control block (address of MXUSR)
; 11 Remove any RSX's below BYE. This is an immediate
; removal via a call to the CPM3 LOADER. I am hoping
; for future KMD support of this function so that any
; uploads will not go into a library currently opend
; by LD in the upload area.
; 101 Initialize function code
; 102 Terminate function code
;
;
; Miscellaneous data/constants
;
INIFLG: DB NOTINIT ; If not reset, all operations rejected
INIT EQU 00 ; Initialized
NOTINIT EQU 0FFH ; Not initialized
;
;
;-----------------------------------------------------------------------
; Entry point to the RSX
;-----------------------------------------------------------------------
;
FTEST: MOV A,C ; Get BDOS function
CPI 60 ; Could this one be for us?
JNZ NEXT ; Nope - ignore this function
;
LDAX D ; Get the sub-function
ENDIF ; CPM3
;
IF CPM3 AND CCPPLUS
CPI 4 ; Is it bye test for CCP+?
JZ TSTBYE
ENDIF ; CPM3 AND CCPPLUS
;
IF CPM3
CPI 7 ; Is it return Variables address
JZ GMXUSR
CPI 11 ; Is it remove lower RSX's ?
JZ DELRSX
CPI 101 ; Is it initialize?
JZ RSXINT
CPI 102 ; Is it terminate?
JZ RSXTRM
JMP NEXT ; No match, try next RSX
;
;-----------------------------------------------------------------------
; RSX control functions
;-----------------------------------------------------------------------
;
; Initialize the RSX environment for subsequent calls
;
; This routine establishes the environment for all other calls to the
; RSX. The operation is completed only if the RSX is not in an initial-
; ized state. If the RSX is already initialized, the function is
; bypassed and an error status is passed back to the caller.
;
RSXINT: LDA INIFLG ; Get the initialize indicator
CPI NOTINIT ; Is this a clean copy?
JNZ RSXIN2 ; No - can't reinitialize, use RESET
XRA A ; Get a zero
STA REMOV ; Mark the RSX resident
STA INIFLG ; And mark this RSX as open for business
ENDIF ; CPM3
;
IF COMFILE AND CPM3
LXI H,COMFCB+1 ; BBS com filename
LXI D,ENTMSG ; Display buffer
MVI B,8 ; Length of filename
;
STAR1: MOV A,M ; Move it to display buffer
CPI ' ' ; Stop on first space
JZ STAR2
STAX D
INX D
INX H
DCR B
JNZ STAR1 ; Loop until space or 8 chars found
;
STAR2: XRA A
STAX D ; Store 0 as print terminator
ENDIF ; COMFILE AND CPM3
;
IF EXFILE AND CPM3
LXI H,EXITFCB+1 ; Exit .COM filename
LXI D,EXTMSG ; Display buffer
MVI B,8 ; Length of filename
;
STAR3: MOV A,M ; Move it to display buffer
CPI ' ' ; Stop on first space
JZ STAR4
STAX D
INX D
INX H
DCR B
JNZ STAR3 ; Loop until space or 8 chars found
;
STAR4: XRA A
STAX D ; Store 0 as print terminator
ENDIF ; EXFILE AND CPM3
;
IF MSGFIL AND CPM3
LXI H,MSGFCB+1 ; Message com filename
LXI D,MSGMSG ; Display buffer
MVI B,8 ; Length of filename
;
STAR5: MOV A,M ; Move it to display buffer
CPI ' ' ; Stop on first space
JZ STAR6
STAX D
INX D
INX H
DCR B
JNZ STAR5 ; Loop until space or 8 chars found
;
STAR6: XRA A
STAX D ; Store 0 as print terminator
ENDIF ; MSGFIL AND CPM3
;
IF LMBELL AND CPM3
LDA BELLON
CMA
STA KILBEL ; Prep the low memory bell flag
ENDIF ; LMBELL AND CPM3
;
IF CPM3
JMP BGOBJ2 ; Go fire it up
;
RSXIN2:
MVI A,0FFH ; Get an error code
;
RSXIN9: RET ; All done - return to caller
;.....
;
;
; Disengage this RSX
;
RSXTRM: CALL MDCARCK ; Check for caller still logged on
JNZ START0 ; Have carrier - log caller off, reset
CALL UNPATCH ; Remove BIOS overrides
JMP BGOBJ2 ; Clean up and restart this program
;
RSXCLR: MVI A,0FFH
STA INIFLG ; Reset the initializaton flag to pre-
; Vent further access
STA REMOV ; Flag to drop this RSX on next warm boot
XRA A ; Get a zero
RET
ENDIF ; CPM3
;
IF CPM3 AND CCPPLUS
;........
;
;Bye present test for CCP+
;
TSTBYE:
XRA A ; Say that we are here
RET
ENDIF ; CPM3 AND CCPPLUS
;
IF CPM3
;.......
;
;Return address of bye control block
;
GMXUSR:
LXI H,MXUSR
RET
ENDIF ; CPM3
;
;.......
;
;Delete any RSX's below bye
;
DELRSX: IF CPM3 AND HISTRSX
MVI C,60 ; BDOS function to call an RSX
LXI D,RSXCL ; Parameter passed to RSX
CALL NEXT
ENDIF ; CPM3 AND HISTRSX
;
IF CPM3
LHLD PREV ; Get address of previous RSX
MVI L,0EH ; Point to remove flag
MVI C,59 ; So that the loader will
LXI D,0 ; Remove the RSX's
DELLP:
MOV A,H
ORA A ; At base page?
JZ NEXT ; All done. Let loader do it.
MVI M,0FFH ; Set remove flag
DCR L
MOV H,M ; Get previous RSX page
INR L ; Back to remove flag
JMP DELLP
ENDIF ; CPM3
;.....
;
;
; Set aside space for the stack region
;
DS 40
ISTACK: DW 0 ; Top of stack
;
;
;-----------------------------------------------------------------------
;
; THE FOLLOWING CODE GETS MOVED
; TO HIGH RAM BY THE LOADER OR RSX
; PROGRAM, WHERE IT IS EXECUTED.
;
;-----------------------------------------------------------------------
;
IF NOT CPM3
BEGOBJ: JMP 0 ; Filled by BEGIN
ENDIF ; NOT CPM3
;
BGOBJ2: JMP START0 ; Hop over fixed vectors
;
MCBOOT: JMP MBOOT ; Off to warm boot
JMP PRNLOG ; Go print out items of interest
;.....
;
;
; Variables follow in a predefined order that can be manipulated by a
; passworded or other program to give special users different capabili-
; ties.
;
;-----------------------------------------------------------------------
;
; Here is a quickie handy reference table to use so we do not get mixed
; up. Please do not change the order of it in any future changes.
;
; |mxusr|mxdrv|toval|nulls|ulcsw|lfeeds|wrtloc|hardon|lostflg|covect|
; |1 byt|1 byt|1 byt|1 byt|1 byt|1 byte|1 byte|1 byte|1 byte |2 byes|
;
; |BYE |bell |stat |lcbuf|mxtme|rtcbuf|beeps|
; |3 byt|1 byt|1 byt|2 byt|1 byt|2 byte|1 byt|
;-----------------------------------------------------------------------
;
MXUSR: DB MAXUSR ; Runtime maximum user area available
MXDRV: DB MAXDRV ; Runtime maximum drive available
TOVAL: DB TOVALUE ; Number of mins. to wait before timeout
NULLS: DB 0 ; Number of nulls after <cr>
ULCSW: DB 0 ; Upper case only switch (32=upper case)
LFEEDS: DB 0 ; Line feed mask (0=don't mask)
WRTLOC: DB 0 ; Location RBBS pokes so BYE won't hang
HARDON: DB 0FFH ; If 0, hardlog is deactivated
MDMOFF: DB 0 ; If 0FFH, do not output to modem
COVECT: DW 0 ; Console output vector for XMODEM
HDROFF EQU $-MCBOOT ; Offset to 'BYE' that follows
DB 'BYE' ; Tells XMODEM that BYE is being used
BELLON: DB 0FFH ; If 0FFH ok to send bell (Chat) to con-
; Sole, 00H=belloff. This only affects
; Your initial default choice
LCPTR: JMP LCDATA ; First byte is user access restrictions
; And flags while user is logged on,
; Used for his total time-on after
; Logoff. LCDATA is address of buffer
; For NO25TH data, NO25BF in length
MXTIME: JMP RTCBUF ; First bye holds maximum time allowed
; Next 2 bytes point to the real time
; Clock buffer
BEEPFL: DB 0 ; Flag to enable/disable inactivity beep
; so we don't affect Zmodem transfers
; 0 = beeps enabled, 0FFH = beeps off
;
; end of BYE5's fixed lookup table
;-----------------------------------------------------------------------
;
LCTON EQU LCPTR ; Byte to store last caller's time-on-
; System value (in binary). You may
; Equate this to a low-memory byte or
; Use this byte in the BYE fixed var-
; Iable table...can then be used by
; Your entry/exit program to determine
; How long the previous caller was on.
;
;-----------------------------------------------------------------------
;
; THIS IS THE OFFICIAL START OF THE BYE PROGRAM
;
;-----------------------------------------------------------------------
;
; ++++ Install your user defined subroutines here ++++
;
; You may install a subroutine here that has the label SRUDEF
; that can be called from a transient program like your entry/
; exit .com file. To access it, MVI C,84 CALL BDOS from your
; program. Make sure this subroutine has a RET at the end.
; The transient program making a BDOS 84 call may pass data to
; this subroutine in any register(s) except A and C. This routine
; can return data to the calling program in any register(s).
;
SRUDEF: RET ; SubRoutine U DEFine for BDOS call 84
;
;-----------------------------------------------------------------------
;
; ++++ Install your I/O port insert here ++++
; or select one from the BYE5-INS.LBR
IF ATR
; B5AT-1.INS - SWP ATR8000 insert for BYE5 - 11/2/88
;
; Using ATR8000 ROM and DTR/CTS signals
; by Marc Newman
; The Black Box BBS
; 713-480-2686
;
;
; Note: This is an insert, not an overlay.
;
; = = = = = = = = = = = = = = = = = =
;
; 11/02/88 Written for use with BYE5 - Marc Newman
;
; = = = = = = = = = = = = = = = = = =
;
;
;
;
; Divisors for the baudrate generator
;
BD300 EQU 034a0h ; 300 baud
BD450 EQU 027a0h ; 450 bps
BD1200 EQU 00da0h ; 1200 bps
bd2400 equ 06850h ; 2400 bps
;
cominit equ 0f7efh ;atr8000 baud rate routine
comout equ 0f79ah ;atr8000 modem output routine
cominp equ 0f738h ;atr8000 modem input routine
comstat equ 0f715h ;atr8000 modem status routine
;
ctsprt equ 50h ;carrier detect port
ctsmsk equ 02h ;carrier detect mask
;
dtrprt equ 55h ;data terminal ready port
dtrmsk equ 01h ;mask for terminal ready port
;
rngprt equ 50h ;ring signal port
rngmsk equ 04h ;ring signal mask
;
;
;-----------------------------------------------------------------------
;
; See if we still have a carrier - if not, return with the zero flag set
;
MDCARCK:in ctsprt ; get carrier status
ani ctsmsk ; Check for carrier
JZ MDCRCK1 ; GOT IT
XRA A ; RETURN ZERO (FALSE)
RET
MDCRCK1:ORI 0FFH ; RETURN FF (TRUE)
RET
;.....
;
;
; Disconnect and wait for an incoming call
;
MDINIT: MVI A,DTRMSK ;TURN DTR OFF
out dtrprt ;hang up the phone
;
PUSH B ; Save in case it's being used elsewhere
MVI B,10 ; 1 second delay to drop any carrier
;
OFFTI: CALL DELAY ; 1 second delay
DCR B
JNZ OFFTI ; Keep looping until finished
;
XRA A ; Setup to turn DTR back on
OUT DTRPRT
mvi b,10
OFFTI1: call delay ; 1 second delay
dcr b
jnz offti1
;
IF IMODEM ; If using an intellegent modem
CALL IMINIT ; Go initialize it now
ENDIF ; IMODEM
;
POP B ; RESTORE BC
;
RET
;.....
;
;
; Input a character from the modem port
;
MDINP: push b
push d
push h
call cominp ; Get character
pop h
pop d
pop b
RET
;.....
;
;
; Check the status to see if a character is available. If not, return
; with the zero flag set. If yes, use 0FFH to clear the flag.
;
MDINST:
push b
push d
push h
call comstat ; Get status
ORA A ; restore registers
jz mdinst1
ori 0ffh
jmp mdinst2
mdinst1:xra a ; Otherwise set the proper flag
mdinst2:pop h
pop d
pop b
RET
;.....
;
;
; Send a character to the modem
;
MDOUTP: PUSH PSW
push b
push d
push h
mov c,a
call comout ; Send it
pop h
pop d
pop b
POP PSW
RET
;.....
;
;
; See if the output is ready for another character
;
MDOUTST:ORI 0FFH ; ATR8000 is a bitbanger,
RET ; so it is always ready for output
;.....
;
;
; Reinitialize the modem and hang up the phone by dropping DTR and
; leaving it inactive.
;
MDQUIT: mvi a,dtrmsk
out dtrprt
IF IMODEM
CALL IMQUIT
ENDIF ; IMODEM
;
;
; Called by the main program after caller types BYE
;
MDSTOP: mvi a,dtrmsk ; Hang up the modem
OUT dtrprt
RET
;.....
;
;
; The following routine sets the baud rate. BYE5 asks for the maximum
; speed you have available.
;
;
SET300: lxi b,BD300
JMP SETBAUD
;
SET1200:lxΘ b,BD1200
JMP SETBAUD
;
SET2400:lxi b,BD2400
;
;
; Sets the baudrate
;
SETBAUD:call cominit ;call ATR8000 baud rate routine
XRA A ; Say baudrate is ok
RET
;.....
ENDIF ;ATR
;
IF NOT ATR
; B5KP-1.INS - Kaypro insert for BYE5 - 07/17/85
;
; Z80-SIO and 8116 baudrate generator
; by Irv Hoff
;
;
; Note: This is an insert, not an overlay.
;
; = = = = = = = = = = = = = = = = = =
;
; 07/17/85 Written for use with BYE5 - Irv Hoff
;
; = = = = = = = = = = = = = = = = = =
;
;
PORT EQU 04H ; Data port
MDCTL1 EQU PORT+2 ; Modem control port
BRPORT EQU 00H ; Baud rate generator port
;
MDRCV EQU 1 ; Modem receive ready bit
MDSND EQU 4 ; Modem send ready bit
MDDCD EQU 8 ; Data carrier detect
;
;
; Divisors for the 8116 baudrate generator
;
BD300 EQU 5 ; 300 baud
BD1200 EQU 7 ; 1200 bps
BD2400 EQU 10 ; 2400 bps
;
;
;-----------------------------------------------------------------------
;
; See if we still have a carrier - if not, return with the zero flat set
;
MDCARCK:MVI A,10H ; Reset status
OUT MDCTL1
IN MDCTL1 ; Get status
ANI MDDCD ; Check for carrier
RET
;.....
;
;
; Disconnect and wait for an incoming call
;
MDINIT: MVI A,0 ; Setup to write register 0
OUT MDCTL1
MVI A,18H ; Reset channel
OUT MDCTL1
;
MVI A,4 ; Setup to write register 4
OUT MDCTL1
MVI A,44H ; Set 16x, 1 stop bit, no parity
OUT MDCTL1
;
MVI A,3 ; Setup to write register 3
OUT MDCTL1
MVI A,0C1H ; 8 bits, Rx enable
OUT MDCTL1
;
MVI A,5 ; Setup to write register 5
OUT MDCTL1
MVI A,68H ; DTR off
OUT MDCTL1
;
PUSH B ; Save in case it's being used elsewhere
MVI B,20 ; 2 second delay to drop any carrier
;
OFFTI: CALL DELAY ; 1 second delay
DCR B
JNZ OFFTI ; Keep looping until finished
POP B ; Restore 'BC'
;
MVI A,5 ; Setup to write register 5
OUT MDCTL1
MVI A,0E8H ; Turn DTR back on
OUT MDCTL1
;
IF IMODEM ; If using an intellegent modem
CALL IMINIT ; Go initialize it now
ENDIF ; IMODEM
;
RET
;.....
;
;
; Input a character from the modem port
;
MDINP: IN PORT ; Get character
RET
;.....
;
;
; Check the status to see if a character is available. If not, return
; with the zero flag set. If yes, use 0FFH to clear the flag.
;
MDINST: IN MDCTL1 ; Get status
ANI MDRCV ; Got a character
RZ ; Return if none
ORI 0FFH ; Otherwise set the proper flag
RET
;.....
;
;
; Send a character to the modem
;
MDOUTP: OUT PORT ; Send it
RET
;.....
;
;
; See if the output is ready for another character
;
MDOUTST:IN MDCTL1 ; Get status
ANI MDSND ; Ready for a character?
RET
;.....
;
;
; Reinitialize the modem and hang up the phone by dropping DTR and
; leaving it inactive.
;
MDQUIT: IF IMODEM
CALL IMQUIT
ENDIF ; IMODEM
;
;
; Called by the main program after caller types BYE
;
MDSTOP: MVI A,5 ; Setup to write register 5
OUT MDCTL1
MVI A,68H ; Turn off DTR until next time
OUT MDCTL1
RET
;.....
;
;
; The following routine sets the baud rate. BYE5 asks for the maximum
; speed you have available.
;
SETINV: ORI 0FFH ; Make sure zero flag is not set
RET
;.....
;
;
SET300: MVI A,BD300
JMP SETBAUD
;
SET1200:MVI A,BD1200
JMP SETBAUD
;
SET2400:MVI A,BD2400
;
;
; Sets the baudrate
;
SETBAUD:OUT BRPORT
XRA A ; Say baudrate is ok
RET
;.....
;
; end
;------------------------------------------------------------------------
ENDIF ;NOT ATR
;
; end
;-----------------------------------------------------------------------
;
;-----------------------------------------------------------------------
;
; ++++ Install your Modem dependent insert here ++++
; (If B5IM is YES you don't need one)
;
;-----------------------------------------------------------------------
;
; ++++ Install your TIME routine here ++++
;
; If you have a clock and wish to use TIMEON or RSPEED, please replace
; the following code with your clock read code. Use as many instruc-
; tions as you need but make sure you store binary, not BCD values in
; CCHOUR and CCMIN. Use RTCBUF to store BCD clock data, then use BCDBIN
; to convert it to binary for CCHOUR and CCMIN. See B5C-QXnn.INS as an
; example of handling a BCD clock, or B5C-SDS.INS for a BIOS interrupt-
; driven clock that runs in binary (hex). All registers are saved before
; TIME is called, so you don't have to save them.
;
; NOTE... Set BCD2BIN to YES if your clock routine calls BCDBIN
; Set BIN2BCD to YES if your clock routine calls BINBCD
;
;
; (Replace the following code with your own clock subroutine)
;
IF (CLOCK OR RSPEED) AND ATR
;
; B5C-KCT1.INS
; 07/17/85 A TIME insert for BYE500 and up
; Wayne Masters
; Potpourri, 408-378-7474
;
; This insert is for the Z80 piggyback clock chip from:
; Kenmore Computer Technology
; 20 Londers Rd.
; Kenmore, N.Y.
; (716) 877-0617
;
; If your computer uses a Z80 chip and does not have a clock
; then this is the clock for you. It installs in minutes.
; Just remove your Z80 chip, install this chip and reinstall
; your Z80 on top. Use an external program to initialize this
; clock prior to loading BYE. (See Z-TIMEn.LBR for this initialization
; program).
;
;
; RTCBUF will have HH, MM, SS, YY, YY, MM, DD as BCD values (see label)
; CCMIN is address for storing current minutes in binary
; CCHOUR is address for current hour in binary.
;
;***********************************************************************
ZPORT EQU 060H ; Board shipped with this as default address
; Change address if you change address jumpers
CENTURY EQU 019H ; Change this in year 2000
;
TIME: IN ZPORT+2 ; Seconds
STA RTCBUF+2
IN ZPORT+3 ; Get BCD value for minutes
STA RTCBUF+1
CALL BCDBIN ; Convert BCD minutes to binary
STA CCMIN ; Update the current minute
IN ZPORT+4 ; Get BCD value for hour
STA RTCBUF
CALL BCDBIN ; Convert BCD hour to binary
STA CCHOUR ; Update the current hour
IN ZPORT+6 ; Day of month
STA RTCBUF+6
IN ZPORT+7 ; Month of year
STA RTCBUF+5
IN ZPORT+9 ; Year of century
STA RTCBUF+4
MVI A,CENTURY ; Set to 19 now
STA RTCBUF+3
RET ; Return
;
; End of TIME routine for BYE500 and up.
;------------------------------------------------------------------------
;
ENDIF ; CLOCK OR RSPEED
;
IF (CLOCK OR RSPEED) AND (NOT ATR)
; NUC-ADV.INS - KayPro 2/4/10 with Advent Products RTC - 06/17/86
;
; Note: This is an insert, not an overlay.
;
; ========
; 06/17/86 First version based on NUC-KP4.INS and time routine found in
; M80CLK.MAC provided with Advent clock - Murray Simsolo
; ========
;
; Use the program CLK.COM supplied by Advent to initialize your clock with
; correct date/time prior to running NUBYE.
;
;
CENTURY EQU 19H ; 19h = 19 bcd, reset this every 100 years
RTCA EQU 90H ; Clock I/O port address
YRREG EQU 9 ; Year register of Advent clock
;
TIME: MVI C,RTCA ; Get port address in C
RETRY: LXI H,LOCBUF ; Point to time save area
MVI B,2 ; Start with seconds
DB 0EDH,078H ; IN A,(C) Read seconds in A
MVI B,YRREG ; Set up to read the year
DB 0EDH,0A2H ; INI Save in temp buffer
DCR B ; Skip to register 7
MVI E,6 ; Set up loop
;
BURST: DB 0EDH,0A2H ; INI Get the clock data
DCR E ; Count down one
JNZ BURST ; Go get more data
;
; See if the clock rolled over during the reads.
;
DCX H ; Point to temporary buffer
CMP M ; Did clock roll?
JNZ RETRY ; Yes, go read again
;
; Format the date and time for bye's realtime clock buffer
;
LDA LOCBUF+6 ; BCD seconds
STA RTCBUF+2
;
LDA LOCBUF+5 ; BCD minutes
STA RTCBUF+1
CALL BCDBIN
STA CCMIN
;
LDA LOCBUF+4 ; BCD hours
STA RTCBUF
CALL BCDBIN
STA CCHOUR
;
LDA LOCBUF+2 ; BCD day of month
STA RTCBUF+6
;
LDA LOCBUF+1 ; BCD month
STA RTCBUF+5
;
MVI A,CENTURY
STA RTCBUF+3
LDA LOCBUF ; BCD year
STA RTCBUF+4
RET ; All done
;
LOCBUF: DB 0,0,0,0,0,0,0 ; Year, Month, Day of Month, Day of Week,
; Hour, Minute, Second
;
;
; end of insert
;
;-----------------------------------------------------------------------
ENDIF
;
; end of clock routine
;-----------------------------------------------------------------------
; start B5IM code
;
IF B5IM
IMRING: CALL MDINST ; Character ready from modem?
RZ ; No
CALL MDINP ; Get the modem response code
ANI 7FH ; Strip parity
ENDIF ; B5IM
;
IF B5IM AND PRGRSS
CALL RCDISP ; Display RC for local Sysop
PUSH PSW
LXI H,LFMSG
CALL PRINTL ; Turn up a line on CRT
POP PSW
ENDIF ; PRGRSS
;
IF B5IM
CPI CR
RZ
CPI LF
RZ
CPI '2' ; Ring?
JNZ REDOIT ; No, something wrong, start over
ENDIF ; B5IM
;
IMRIN1: IF B5IM AND (NOT NOATA)
MVI B,22 ; Must let the phone quit ringing first
CALL DLP1 ; Usually takes from 1.4 to 3.7 seconds
CALL EATALL ; Swallow c/r or lf from result code
;
IMRIN2: LXI H,B5ATA
CALL IMSEND ; Send ATA to modem
ENDIF ; B5IM AND NOT NOATA
;
IF B5IM
LXI B,30000 ; Check for RC every 1 ms for 30 secs
;
MDR1: CALL MDINST
JZ RCHEK ; And wait for response
CALL MDINP ; Then fetch it
ANI 07FH ; And strip parity
ENDIF ; B5IM
;
IF B5IM AND PRGRSS
CALL RCDISP ; And show results code (RC)
ENDIF ; B5IM AND PRGRSS
;
IF B5IM
CPI CR
JZ MDR1
CPI LF
JZ MDR1
CPI '2' ; Missed ring indicator?
JZ IMRIN1 ; Answer again
CPI '3' ; Carrier wait timeout?
JZ REDOIT ; Yep, timeout (voice call maybe)
CPI '4' ; Error?
JZ REDOIT ; Start over
CPI '1' ; 300 baud or 2400 bps?
JNZ MDR2 ; No, check for 1200 bps
;
;
; Get next character if first was a '1'
;
CALL CHECK1 ; Let's see if it's a 1, 10 or 11
ENDIF ; B5IM
;
IF B5IM AND PRGRSS
CALL RCDISP ; Show RC to local terminal
ENDIF ; B5IM AND PRGRSS
;
IF B5IM
CPI '0'
JZ SET24 ; For Vadic and Hayes, 10 means 2400 bps
;
JMP SET3 ; Was 1 (300 baud)
;
MDR2: CPI '5' ; 1200 bps?
JZ SET12 ; Yes
CPI '6' ; Some modems use 6
JZ SET24
CPI '9' ; Or 9
JZ SET24 ; For Connect-2400
ENDIF ; B5IM
;
IF B5IM AND ANCHOR
JMP SET3 ; If it wasn't a 3 or 5 it means the
; Anchor connected at 300 but sent RC
; At wrong speed
ENDIF ; B5IM AND ANCHOR
;
IF B5IM
JMP MDR1 ; Wait 30 seconds for valid response
;
RCHEK: CALL KDELAY ; Wait 1 millisecond
DCX B
MOV A,C
ORA B ; Time up?
JNZ MDR1 ; No, Keep trying
;
REDOIT: POP H ; Go reset if none of these responses
LXI H,VCNUM ; Update the voice call
INR M ; Counter
ENDIF ; B5IM
;
IF B5IM AND DISKLOG
CALL OPENLOG ; Make sure log file is on
LXI H,VOCMSG
CALL WRTMSG ; Put voice call message into log
MVI E,0
CALL TSTHRD ; Close the log file
ENDIF ; B5IM AND DISKLOG
;
IF B5IM
LXI H,LFMSG
CALL PRINTL ; Turn up a line on crt
CALL MDSTOP ; Turn dtr off while we reset
JMP HANGUP1
ENDIF ; B5IM
;
IF B5IM AND PRGRSS
RCDISP: PUSH B
PUSH H
PUSH PSW ; Save A
STA RCSHOW
LXI H,RCSHOW ; And show results code (RC)
CALL PRINTL
POP PSW
PUSH PSW
CPI CR
JNZ RCDIS1
MVI A,LF
STA RCSHOW ; Force a LF after a CR
LXI H,RCSHOW
CALL PRINTL
;
RCDIS1: POP PSW
POP H
POP B
RET
ENDIF ; B5IM AND PRGRSS
;.....
;
;
IF B5IM
CHECK1: LXI B,400 ; Try for 400 ms
;
CHECK2: CALL KDELAY
DCX B
MOV A,B
ORA C
JZ CHECK3 ; 600 ms is up
CALL MDINST ; Character ready?
JZ CHECK2 ; No, keep waiting
CALL MDINP ; Yes, fetch it
ANI 07FH ; And strip parity
RET ; And return
;
CHECK3: MVI A,0FFH ; Set error code
RET ; And return
;.....
;
;
SET24: CALL DLP ; 1 sec delay
CALL SET2400 ; Set port to 2400 bps
MVI A,BP2400
STA MSPEED ; Set speed indicator
JMP FINISH
;
SET3: CALL DLP
CALL SET300 ; Set port to 300 baud
MVI A,BP300
STA MSPEED ; Set speed indicator
JMP FINISH
;
SET12: CALL DLP
CALL SET1200 ; Set port to 1200 bps
MVI A,BP1200
STA MSPEED ; And speed indicator
;
FINISH: CALL MDCARCK ; Still have carrier?
JZ REDOIT ; No, reset modem
POP H ; Reset CALL on the stack
CALL PATCH ; Patch the jump table
MVI B,6 ; 6 sec more with 1 sec already
; Used= 1.6 sec
CALL DLP1 ; Wait to enter terminal mode
CALL EATALL ; Clear input port (takes .4 sec more)
JMP ANSW ; And greet the user at his speed
;.....
;
;
; Initialize the modem for normal unattended operation.
;
IMINIT: CALL DLP
CALL EATALL
ENDIF
;
IF B5IM AND DOATZ
LXI H,B5ATZ ; Reset the modem
CALL IMSEND
CALL DLP
CALL EATALL ; Swallow the response
ENDIF ; B5IM AND DOATZ
;
IF B5IM
LXI H,B5INIT
CALL IMSEND ; Go initialize the modem
ENDIF ; B5IM
;
IF B5IM AND SHORTB
CALL DLP
CALL EATALL
LXI H,B5INT1
CALL IMSEND ; Use 2 strings for short buff. modems
ENDIF ; B5IM AND SHORTB
;
IF B5IM AND PRGRSS
IMINT1: CALL CHECK1
CPI 0FFH ; No result code?
JZ IMINT2 ; Yes, inform Sysop and retry
CPI '0' ; Executed ok?
CZ RCDISP ; Display result code
JZ IMINT3 ; And continue
CPI '4' ; Modem error?
CZ RCDISP
JNZ IMINT1 ; Wait for a zero or four or 0FFH
;
IMINT2: LXI H,CMDERR ; We have a 4 or 0FFH
CALL PRINTL ; Inform Sysop of problem
JMP IMINIT ; Try it again
ENDIF ; B5IM AND PRGRSS AND NOT ANCHOR
;
IF B5IM
IMINT3: LXI H,LFMSG
CALL PRINTL ; Turn up a line on crt
CALL DLP
CALL EATALL ; Get any garble from the modem
RET
;.....
;
;
; Delay about one second to let modem get stabilized before or after a
; command string.
;
DLP: MVI B,10
;
DLP1: CALL DELAY
DCR B
JNZ DLP1
RET
;
EATALL: CALL CHECK1
CPI 0FFH ; All characters eaten?
JNZ EATALL ; No, keep eating
RET
;.....
;
;
; De-initiaize the modem. When the operator uses CTL-C followed by any-
; thing but "R", this call will return the modem to default settings.
;
IMQUIT: LXI H,LFMSG
CALL PRINTL ; Turn up a line on crt
ENDIF ; B5IM
;
IF B5IM AND DOATZ
CALL DLP
CALL EATALL
LXI H,B5ATZ
CALL IMSEND ; Send ATZ message to modem
ENDIF ; B5IM AND DOATZ
;
IF B5IM
CALL DLP
CALL EATALL
ENDIF ; B5IM
;
IF B5IM AND (NOT OFFHK)
LXI H,B5USR
CALL IMSEND ; Send ATS0=0 to modem
CALL EATALL
ENDIF ; B5IM AND NOT OFFHK
;
IF B5IM AND OFFHK
LXI H,B5ATH1 ; Send ATH1 to the modem
CALL IMSEND
ENDIF ; B5IM AND OFFHK
;
IF B5IM
RET
;.....
;
;
; Send a command string to the modem. (If ECHO) Verify, reset the modem
; and resend string if echo fails.
;
IMSEND: PUSH B ; Save 'BC' registers
SHLD ADDSTR ; Save start of command string
;
IMSEN1: CALL MDOUTST ; Modem ready for character?
JZ IMSEN1 ; No, go check again
MOV A,M ; Get the character
PUSH PSW
CALL MDOUTP ; Send the character
POP PSW
ENDIF ; B5IM
;
IF B5IM AND PRGRSS
CALL RCDISP ; Display the command string
ENDIF ; B5IM AND PRGRSS
;
IF B5IM AND ECHO ; Hayes needs echo checking
CALL CHECK1 ; Get the echo character
CMP M ; Same?
JNZ NOECHO ; No, let's resend entire command string
ENDIF ; B5IM AND ECHO
;
IF B5IM
INX H ; Point to next
MOV A,M ; Get next character
ORA A ; Has all been sent
JNZ IMSEN1 ; No, go send another character
POP B ; Restore the BC registers
RET ; Return past end of message
ENDIF ; B5IM
;
NOECHO: IF B5IM AND ECHO AND PRGRSS
LXI H,NOEMSG
CALL PRINTL ; Inform Sysop of echo error
ENDIF ; B5IM AND ECHO AND PRGRSS
;
IF B5IM AND ECHO
CALL MDOUTST ; Wait for modem ready
JZ NOECHO
MVI A,CR
CALL MDOUTP ; Force a c/r to end command string
CALL DLP ; Let modem settle
CALL EATALL ; Make sure input is clear
LHLD ADDSTR ; Restore address of command string
JMP IMSEN1 ; And send it again
ENDIF ; B5IM AND ECHO
;.....
;
;
IF B5IM AND NODTR
IMHANG: CALL EATALL
MVI B,30 ; Some modems need 3 sec, doesn't hurt
; Others
CALL DLP1 ; This routine will hang up the phone
LXI H,B5ESC ; Using +++ATH
CALL IMSEND
CALL EATALL
MVI B,15
CALL DLP1
LXI H,B5ATH
CALL IMSEND ; For modems without DTR support
CALL DLP
RET
ENDIF ; B5IM AND NODTR
;.....
;
; end of B5IM code
;-----------------------------------------------------------------------
;
IMDONE: CALL DELAY
;
IF NOT NODTR
CALL MDSTOP ; Drop DTR-***This is a new label just
; After MDQUIT that drops DTR and
; Returns.
ENDIF ; NOT NODTR
;
CALL MDCARCK ; Carrier?
RZ ; Carrier gone, return
;
IF B5IM AND NODTR
CALL IMHANG ; Send +++ATH
ENDIF ; B5IM AND NODTR
;
JMP IMDONE ; Keep looping
;
;-----------------------------------------------------------------------
;
; If the carrier is lost - hang up, await ring. Otherwise, say goodbye,
; and hang-up.
;
START0: IF TIMEON
LDA TON
STA LCTON ; Preserve last callers time-on for
; Entry pgm
ENDIF ; TIMEON
;
IF NOT CPM3
LHLD BDOS+1 ; Get beginning address of BYE5 program
SHLD BDADDR ; Save address of BYE5 start
ENDIF ; NOT CPM3
;
;
;
; Patch in BYE's BDOS interceptor
;
IF CPM3
LHLD STARTX+1
ENDIF ; CPM3
;
IF NOT CPM3
LHLD BEGOBJ+1 ; Get real bdos call
ENDIF ; NOT CPM3
;
MOV A,H ; Get high address byte
LXI D,BYERSX ; Have to do it this way to fool the
; Relocator
CMP D ; Already pointed to BYERSX?
JZ NORPTC ; Then don't patch again
SHLD REALBD+1 ; Save it in the interceptor routine
LXI H,BYERSX ; Get address of interceptor routine
;
IF CPM3
SHLD STARTX+1 ; So we intercept BDOS calls
ENDIF ; CPM3
;
IF NOT CPM3
SHLD BEGOBJ+1 ; Save it so it goes through our ex-
; Tended BDOS
ENDIF ; NOT CPM3
;
NORPTC: XRA A ; A=0
STA MDMOFF ; Show no carrier lost
STA ULCSW ; Reset upper/lower case flag
STA LFEEDS ; And line feed flag
STA WRTLOC ; And write-in-progress flag
STA OPTION ; And option flag
;
IF TIMEON AND CLOCK AND (NOT (EXFILE OR TABBY))
CALL MDCARCK
CNZ RMTOS ; Report final time-on-system
ENDIF ; TIMEON AND CLOCK
;
;
; Set MINICK to 'YES' if you use MINICBBS and want to take advantage of
; its feature which can prevent the modem from hanging up if the caller
; should happen to disconnect during a file update. MINICBBS sets the
; high-order bit of IOBYTE (address 0003H) to indicate a file update is
; in progress.
;
IF MINICK
MVI A,IOVAL ; Get proper initial value
STA IOBYTE ; Set it in IOBYTE
ENDIF ; MINICK
;
IF MBBS
LXI SP,STACK
CALL MDCARCK
JZ START1 ; No carrier, skip this
LDA LCDATA
CPI ' ' ; User logged in?
JZ GOODBY ; No, carry on
XRA A
STA 0 ; Prep mbbs
MVI A,0FFH
STA WRTLOC ; To prevent hangup
LDA FCB+1
CPI 'C' ; Comments requested?
JZ MBBSC ; Yes, do comments
ENDIF ; MBBS
;
IF MBBS AND PRNTGB
LXI H,GBMSG
CALL PRINTB ; Say goodbye to user
ENDIF ; MBBS AND PRNTGB
;
IF MBBS
MBBS01: CALL IMDONE ; Drop carrier and fix so phone won't
JMP MBBSNC ; Answer and tell Sysop
;
MBBSC: STA OPTION ; So we know to load MBBS or login
LXI H,MBBS1
CALL PRINTB ; Wait for MBBS to load
CALL LODCOM ; Load mbbs for comments
CALL MDCARCK ; Did user wait for all this?
JZ MBBSNC ; No, tell Sysop and load login
MVI A,0CDH
STA 0 ; So MBBS will ask for comments
CALL 100H ; Now do it
;
MBBSNC: LXI H,MBBS2
CALL PRINTL ; Tell Sysop about log off
MVI A,0FFH
STA MDMOFF ; So BYE5 will handle rest of this
MVI A,'E'
STA OPTION ; So BYE5 will trap MBBS return
CALL LODCOM ; Load login
CALL 100H ; Let login finish user stats
ENDIF ; MBBS
;
CALL MDCARCK ; Call modem carrier check routine
JNZ GOODBY ; We have carrier, so say bye bye...
;
START1: IF COMFILE
LDA FCB+1
STA OPTION ; So remote cannot type BYE E
MVI A,' '
STA FCB+1
ENDIF ; COMFILE
;
;
; Get the System Parameter Block address, common memory base page,
; BDOS base page for use in main program or overlays.
;
IF CPM3
MVI C,GTSCB ; Return base page of SCB
LXI D,SCBPB
CALL BDOS
SHLD SCBBASE ; Save SCB address
MVI L,SCBCOM ; 0FAH = common memory base page
MOV A,M
STA MEMBASE ; Save common memory base page
MVI L,SCBBDOS ; 99H = base page of BDOS
MOV A,M
STA BDOSBASE ; Save base page of BDOS system
ENDIF ; CPM3
;
;
; Identify version of program
;
CALL PATCH ; Copies vectors for PRINTL
CALL UNPATCH
LXI H,VMSG ; Signon message
CALL PRINTL
;
JMP HANGUP ; We know it is local, so prepare for
; Next caller
;
GOODBY: IF EXFILE OR TABBY
JMP LOGOFF ; Run the exit file
ENDIF ; EXFILE OR TABBY
;
IF PRNTGB AND (NOT (EXFILE OR TABBY))
LXI H,GBMSG ; Goodbye message
CALL PRINTB ; Print this message
ENDIF ; PRNTGB AND NOT EXFILE OR TABBY
;
IF NOT (EXFILE OR TABBY)
CALL IMDONE ; Hang up the phone before doing this
CALL UNPATCH ; Undo BIOS patches
ENDIF ; NOT EXFILE OR TABBY
;
;.....
;
IF DISKLOG AND (NOT (EXFILE OR TABBY))
LXI H,DSCMSG ; Disconnect message
CALL WRTMSG ; Put it into log file
ENDIF ; DISKLOG AND NOT EXFILE OR TABBY
;
;
; Nobody there, or we are done.
;
HANGUP: LXI SP,STACK ; Set up local stack
;
IF DISKLOG
XRA A
STA BDOSFL
STA LOGTOG
MOV E,A
CALL TSTHRD ; This will close log file
ENDIF
;
IF CPM3
CALL DELRSX ; Remove any RSX's below BYE
LXI D,DEFPW
MVI C,DEFPAS
CALL REALBD ; Set default password to blanks
ENDIF ; CPM3
;
IF TABBY ; Makes TABBY output more readable
LXI H,CRMSG
CALL PRINTL
ENDIF ; TABBY
;
IF COMFILE
LXI H,ENTMSG
CALL PRINTL ; Show it's the entry file
CALL LODCOM ; Load the .COM file
ENDIF ; COMFILE
;
;
; Set drive/user, then give summary and initialize for next call
;
HANGUP1:MVI A,WBDRIV ; Force next warmboot to user 0
STA 0004H ; And drive wbdriv
;
IF CPM3
CALL SETDRIVE ; Set to wbdriv
XRA A
CALL SETUSER ; Set user to zero
ENDIF ; CPM3
;
XRA A
STA MDMOFF ; Clear modem status
STA WRTLOC ; And wrtloc
STA TON ; Reset time-on-system
STA MSFLAG ; Reset status for no-activity timer
;
IF RTOK
STA RTOKFG ; So RBBS can be re-entered
ENDIF ; RTOK
;
IF CPM3
LHLD SCBBASE ; Get address of SCB
MVI L,0D4H
MOV M,A ; Reset ^P mode
MVI L,0CAH
MOV M,A ; Set CTL-H mode
INR L
DCR A
MOV M,A ; Set RUB/DEL mode
ENDIF ; CPM3
;
IF CPM3 AND CCPPLUS
MVI L,0A4H
MOV A,M
ORI 80H ; Turn on directory name display
MOV M,A
ENDIF ; CPM3 AND CCPPLUS
;
IF CPM3
MOV D,H
MVI E,0E8H ; Point to drive search chain
LXI H,DRVSRC
MVI B,4
CALL MOVE ; Set the drive search chain
ENDIF
;
IF NO25TH OR MBBS
LXI H,LFMSG
CALL PRINTL
LXI H,LCDATA
CALL PRINTL ; Show Sysop who was just on
ENDIF ; NO25TH
;
IF NO25TH OR MBBS
LXI H,LCDATA
MVI B,NO25BF
CALL ZEROM ; Fill with zeros for PRINTL
LXI H,LCFILL
LXI D,LCDATA
MVI B,15
CALL MOVE ; Put filler msg into LASTCALR for now
ENDIF ; NO25TH OR MBBS
;
IF TIMEON
LXI H,TONMSG
CALL PRINTL ; Show him how long he was on
XRA A
LXI H,TONMSD
CALL DEC8 ; So next message will be 0
ENDIF ; TIMEON
;
IF TIMEON OR CLOCK
MVI A,255
STA TCHKFG ; Show clock not read
ENDIF ; TIMEON OR CLOCK
;
CALL CALSUM ; Give Sysop call summary
;
IF B5IM AND HS9600
CALL SET9600
ENDIF ; B5IM AND HS9600
;
IF B5IM AND HS4800
CALL SET4800
ENDIF ; B5IM AND HS4800
;
IF B5IM AND HS2400
CALL SET2400 ; Talk to the modem at its highest speed
ENDIF ; B5IM AND HS2400
;
IF B5IM AND HS1200
CALL SET1200
ENDIF ; B5IM AND HS1200
;
IF B5IM AND HS300
CALL SET300
ENDIF ; B5IM AND HS300
;
CALL MDINIT ; Call modem initialization routine
;
MVI A,0C3H ; Clear any traps left from .COM file
STA 0
;
LDA LCDFLG
ORA A ; Sysop want the system?
JNZ BEXCPM ; Yes, exit with bells
;
IF CLRSCR
CALL CLEARIT ; Clear local crt screen
ENDIF ; CLRSCR
;
IF COMFILE
LDA OPTION
CPI 'E' ; Execute comfile locally?
JNZ MOTOFF ; No, continue
ENDIF ; COMFILE
;
ERUN: IF COMFILE AND B5IM
CALL IMQUIT
ENDIF ; COMFILE AND B5IM
;
IF COMFILE AND (NOT B5IM)
CALL MDQUIT ; Fix modem so won't answer phone
ENDIF ; COMFILE AND NOT B5IM
;
IF COMFILE
MVI A,0FFH
STA MDMOFF ; Turn modem off
STA WRTLOC ; And write flag
MVI A,'L'-30H
STA MSPEED ; Some BBS's need this, rest don't care
JMP ANSW ; Skip this
ENDIF ; COMFILE
;
MOTOFF: IF MOTOR
CALL DSKOFF ; Turn off drives
ENDIF ; MOTOR
;.....
;
;
; Await ringing - check local keyboard for CTL-C exit request. Note:
; Must do input via BDOS because CBIOS patches are not done until the
; call comes in.
;
RINGWT:
IF TABBY
CALL GETNXE ; Find NXTEVENT file and read
ENDIF ; TABBY
;
IF TABBY AND (NOT CLKDSP)
LDA NXTHR
CALL BCDBIN
LXI H,EVENHR
CALL DEC8
;
LDA NXTMN
CALL BCDBIN
LXI H,EVENMN
CALL DEC8
LXI H,TIMESG
CALL PRINTL
ENDIF ;TABBY AND NOT CLKDSP
;
RINGW:
IF CLKDSP OR TABBY
CALL TIME ; Update time buffer
ENDIF ; CLKDSP OR TABBY
;
IF CLKDSP
;
; Format the date and time for bye's realtime clock buffer
;
LDA RTCBUF+2 ; BCD seconds
CALL BCDBIN
LXI H,TIMESG+17
CALL DEC8
;
LDA RTCBUF+1 ; BCD minutes
CALL BCDBIN ; Convert to binary
LXI H,TIMESG+14
CALL DEC8
;
LDA RTCBUF ; BCD hours
CALL BCDBIN ; Convert to binary
LXI H,TIMESG+11
CALL DEC8
;
LDA RTCBUF+6 ;BCD day
CALL BCDBIN
LXI H,TIMESG+8
CALL DEC8
;
LDA RTCBUF+5 ; BCD month
CALL BCDBIN
LXI H,TIMESG+5
CALL DEC8
;
LDA RTCBUF+4 ; BCD year
CALL BCDBIN
LXI H,TIMESG+2
CALL DEC8
ENDIF ; CLKDSP
;
IF CLKDSP AND TABBY
LDA NXTHR
CALL BCDBIN
LXI H,EVENHR
CALL DEC8
;
LDA NXTMN
CALL BCDBIN
LXI H,EVENMN
CALL DEC8
LXI H,TIMESG
CALL PRINTL
ENDIF ; CLKDSP AND TABBY
;
;
IF TABBY
LDA NXTHR ; Hour of next event for Tabby
LXI H,RTCBUF
CMP M ; Right hour?
JNZ RINGW0 ; Nope
;
LDA NXTMN ; Minute of next event for Tabby
LXI H,RTCBUF+1 ; Address of minutes
CMP M ; Right minute?
JNZ RINGW0 ; Nope
JMP TBYEXIT
ENDIF ; TABBY
;
RINGW0: CALL CONSTAT
ORA A
JZ RINGW1
CALL VCONIN ; Character typed
ANI 7FH ; Strip parity bit
CPI 'C'-40H ; CTL-C?
CZ USRCHK ; Check for exit
CALL CKFUNC ; Check for function keys
RINGW1: IF B5IM
CALL IMRING ; This routine does it all
JZ RINGW
ENDIF ; B5IM
;
IF NOT B5IM
CALL MDCARCK ; Carrier?
JZ RINGW ; No, keep looping
ENDIF ; NOT B5IM
;
;
;-----------------------------------------------------------------------
; answer routine
;
ANSW: IF NOT CPM3
CALL BDCHEK
ENDIF ; NOT CPM3
;
IF MOTOR
CALL DSKON ; Turn on drives
ENDIF ; MOTOR
;
IF (NOT USEZCPR) AND (ZCPR2 OR ZCPR3)
MVI A,MAXUSR ; Reset maximum user area
STA MXUSR ; Set it in bye
INR A ; Bump it
STA MAXUSER ; Set it in ZCPR
MVI A,MAXDRV ; Reset maximum drive
STA MXDRV
DCR A
STA MAXDRIV
ENDIF ; ZCPR2 OR ZCPR3 AND NOT USEZCPR
;
IF CHGPATH ; If external ZCPR path
CALL REMPAT ; Set up the secure path for caller
ENDIF ; CHGPATH
;
XRA A ; Make sure line feeds are on again
STA LFEEDS
STA CDOFF ; Limit for waiting for c/r
STA FKFLAG ; F-key lead-in flag
;
IF ZCPR2 OR ZCPR3 ; Only when using ZCPR w/secure mode
STA WHEEL ; Answer the phone in non-wheel mode
ENDIF ; ZCPR
;
MVI A,TOVALUE ; Reset timeout count
STA TOVAL
;
IF COMFILE
LDA OPTION
CPI 'E'
JZ WELCOME ; Skip this if running local
ENDIF ; COMFILE
;
LXI H,CWCAR ; Get # of attempts
INR M ; And add one
;
IF B5IM
JMP WELCOME ; Skip the old fashion CR detect method
ENDIF ; B5IM
;
IF NOT B5IM
ANSWA: CALL SET300
MVI A,BP300 ; Poke in MSPEED value
STA MSPEED
ENDIF ; NOT B5IM
;
IF NOT TABBY
CALL MDINP ; Clear garbage characters
CALL MDINP
ENDIF ; NOT TABBY
;
IF NOT B5IM
;
;
; Now test input for baud rate - FIRST, check for 300 baud
;
ANSWB: CALL PATCH ; Patch jump table
ENDIF ; NOT B5IM
;
IF PRGRSS AND (NOT B5IM)
LXI H,MSG30
CALL PRINTL ; Print locally
ENDIF ; PRGRSS AND NOT B5IM
;
IF NOT B5IM
CALL TSTBAUD ; See if 300 baud
JZ WELCOME ; Yes, exit
ENDIF ; NOT B5IM
;
;
; Now check for 1200 bps
;
IF PRGRSS AND (NOT B5IM) AND (HS1200 OR HS2400)
LXI H,MSG12
CALL PRINTL ; Print locally
ENDIF ; PRGRSS AND NOT B5IM
;
IF (NOT B5IM) AND (HS1200 OR HS2400)
CALL SET1200 ; Now check 1200 bps
JNZ ANS0
MVI A,BP1200 ; Set the MSPEED pointer
STA MSPEED
; CALL MDINP ; Clear garbage (MKN111788)
CALL TSTBAUD ; Check baud rate
JZ WELCOME
ENDIF ; NOT B5IM
;
ANS0: IF PRGRSS AND (NOT B5IM) AND HS2400
LXI H,MSG24
CALL PRINTL ; Print locally
ENDIF ; PRGRSS AND NOT B5IM
;
IF (NOT B5IM) AND HS2400
CALL SET2400 ; Check for 2400 baud
JNZ BADDO ; Start over
MVI A,BP2400 ; Set speed indicator
STA MSPEED
CALL MDINP ; Clear garbage
CALL TSTBAUD ; Check it
JZ WELCOME
ENDIF ; NOT B5IM AND HS2400
;
IF NOT B5IM
BADDO: CALL UNPATCH ; Restore original jump table
JMP ANSWA ; Test more - invalid baud rate
ENDIF ; NOT B5IM
;.....
;
IF CPM3
DRVSRC: DB SDRV1,SDRV2,SDRV3,SDRV4 ; Default drive search chain
DEFPW: DB ' ' ; Default password
RSXCL: DB 56 ; Subfunction to clear command line
; History from HIST RSX
ENDIF ; CPM3
;
; end of answer routine
;-----------------------------------------------------------------------
;
IF NOT CPM3
BDCHEK: PUSH H ; To make truly universal, (???) this
DB LXIH ; Program always re-stores the BDOS
;
BDADDR: DW 0000H ; Pointer at 6 and 7 set up location for
SHLD 6 ; Beginning address of CONSOLX CTL
POP H ; At every chance. This replaces the
RET ; WMLOCK & OLDBD as in BYE2 AND BYE3
ENDIF ; NOT CPM3
;.....
;
;
;-----------------------------------------------------------------------
;
; Common routine to check for carrier lost - called from console out
;
CHECK: IF MINICK
LDA IOBYTE ; Get IOBYTE
ANI 80H ; Test for disk update
RNZ ; Busy, wait until done
ENDIF ; MINICK
;
IF RBBS OR MBBS OR PBBS OR QBBS OR DRBBS
LDA WRTLOC ; Get write in progress flag
ORA A
RNZ ; Busy, wait until done
ENDIF ; RBBS OR MBBS OR PBBS OR QBBS OR DRBBS
;
LDA MDMOFF
ORA A ; Know modem off?
RNZ ; Yes, skip this
CALL CARCK ; See if carrier still on
RNC ; All ok
;
;
; Carrier is lost, inform Sysop
;
LXI SP,STACK ; Insure valid stack
LXI H,CLMSG ; Carrier lost message
CALL PRINTL ; Send this Message
;
IF DISKLOG
XRA A
STA BDOSFL
LXI H,CARMSG
CALL WRTMSG ; Put carrier lost msg in SYS.LOG
JMP LOGOFF
;
DROPIT:
LXI SP,STACK ; Insure valid stack
XRA A
STA BDOSFL
LXI H,DRPMSG
CALL WRTMSG ; Put dropped message into log
ENDIF ; DISKLOG
;
;
; Come here to log off a user
;
LOGOFF: LXI SP,STACK ; Ensure valid stack
;
IF NOT CPM3
CALL BDCHEK ; In case carrier lost in LUX
ENDIF ; NOT CPM3
;
CALL PATCH ; We need this so bye is in the loop
;
IF TIMEON
LDA TON
STA LCTON ; Preserve caller's time-on for
; Entry/exit pgm
ENDIF ; TIMEON
;
CALL MDCARCK
JZ LOGOF1 ; Skip over goodby data
;
IF NOT BYHANG
JMP LOGOF2 ; Skip goodbye and hangup
ENDIF ; NOT BYHANG
;
IF TIMEON AND CLOCK
CALL RMTOS ; Report users final timeon
ENDIF ; TIMEON AND CLOCK
;
IF PRNTGB
LXI H,GBMSG
CALL PRINTB ; Say goodbye
ENDIF ; PRNTGB
;
LOGOF1: MVI A,255
STA MDMOFF ; Show known loss of carrier
STA TCHKFG ; Reset time flag
CALL IMDONE ; Make sure phone is disconnected
;
LOGOF2: IF MBBS
XRA A
STA FCB+1 ; Prepare to exit thru MBBS
STA 0
STA MXTIME
LDA LCDATA ; If user was logged in
CPI ' '
JNZ MBBS01 ; User logged in so exit thru MBBS
ENDIF ; MBBS
;
IF EXFILE
LXI H,EXTMSG
CALL PRINTL ; So Sysop knows exit file is executing
MVI C,SETUSR ; Select user area for EXITFILE
MVI E,EXUSR
CALL BDOS
MVI C,SELDSK ; Select default drive for EXITFILE
MVI E,EXDRV-'A'
CALL BDOS
CALL LODEX
CALL 100H
ENDIF ; EXFILE
;
IF (TABBY OR EXFILE) AND (NOT BYHANG)
CALL MDCARCK ; Still have carrier after exfile ran?
JZ TBYEXIT ; No, skip this
ENDIF ; EXFILE AND NOT BYHANG
;
IF CLOCK AND TIMEON AND (EXFILE OR TABBY) AND (NOT BYHANG)
CALL RMTOS ; Print time data
ENDIF ; CLOCK.....
;
IF PRNTGB AND (EXFILE OR TABBY) AND (NOT BYHANG)
LXI H,GBMSG
CALL PRINTB ; Pring goodbye
ENDIF ; PRNTGB...
;
TBYEXIT:
IF TABBY
CALL UNPATCH
LHLD REALBD+1
SHLD BDOS+1 ; RESTORE REAL BDOS
MVI C,SETUSR
MVI E,TBYUSER
CALL BDOS
MVI C,SELDSK
MVI E,TBYDRV-'A'
CALL BDOS
LXI H,CRMSG
CALL PRINTL
LXI H,DSPMSG
CALL PRINTL
CALL LODTBY
CALL MDQUIT ; Make sure no caller left online
MVI A,TBYUSER*010H+TBYDRV-'A' ;This makes SURE we are on
STA 0004H ; the right drive and user for $$$.sub files
ENDIF ; TABBY
;
IF TABBY AND (ZCPR2 OR ZCPR3)
MVI A,0FFH
STA WHEEL ; Let the $$$.SUB file do important commands
ENDIF ; TABBY AND (ZCPR2 OR ZCPR3)
;
IF TABBY AND DISKLOG
MVI E,0
CALL TSTHRD ; Close the disk log
ENDIF ; DISKLOG
;
IF TABBY
MVI A,0
STA 080H ; Make SURE Tabby sees a null command tail
MVI A,' '
STA 05DH
;
JMP 100H ; DISPATCH does it's own return
ENDIF ; TABBY
;
IF NOT TABBY
JMP PREOFF ; Prepare for next caller
ENDIF ; NOT TABBY
;.....
;
;
;-----------------------------------------------------------------------
;
; Function key routines
;
CKFUNC: IF LEADIN
PUSH PSW ; Save character
CPI LEADKY ; Lead-in key typed?
JNZ FKEY1 ; No, see if already typed
MVI A,0FFH ; Yes, set the lead-in flag
STA FKFLAG
POP PSW ; Reset stack
MVI A,07FH ; DEL for buffer
RET
;
FKEY1: LDA FKFLAG
ORA A ; Lead-in already typed?
JZ FKEXIT ; No, exit
XRA A ; Yes, reset the flag
STA FKFLAG
POP PSW ; Get char back
ANI 1FH ; Make it a ctrl character
ENDIF ; LEADIN
;
IF B5IM AND (NOT NOATA)
MOV B,A
PUSH B ; Save the character
CALL MDCARCK ; Carrier?
POP B
MOV A,B
JNZ ANSKNO ; Can't do this with carrier
CPI ANSKEY ; Sysop wants BYE to answer the phone
CZ IMRIN2 ; So do it, IMRIN2 will restore the call
;
ANSKNO: ENDIF ; B5IM AND NOT NOATA
;
IF NO25TH OR MBBS
CPI WHOKEY
JZ WHOSIT ; Display last caller data
ENDIF ; NO25TH OR MBBS
;
IF TIMEON
CPI TIMEKEY
JZ DTIME ; Case running local, allow debug
ENDIF ; TIMEON
;
CPI ZCREEN
JZ CLEARIT ; Sysop wants to clear his screen
CPI BELLKEY
JZ BELLTOG ; Toggle bell on/off
;
IF DISKLOG
CPI LOGKEY
JZ LOGFLP ; Toggle disk log on/off
ENDIF ; DISKLOG
MOV B,A
PUSH B
CALL MDCARCK ; See if carrier is on, because
POP B
MOV A,B
RZ ; The following keys are useless without
; It.
CPI LCKEY
JZ LCDOIT ; Sysop wants the system when caller is thru
CPI ULTKEY
JZ ULTIME ; Give current user unlimited timeon
CPI BLNKKEY ; Turn off caller's output for a moment?
JZ BLNKTOG ; (this is a toggle)
CPI SYSDKEY
JZ SYSDOWN ; Tell caller system is going down
CPI TWITKEY
PUSH PSW
CZ IMDONE ; Hang up on the twit
POP PSW
;
IF NOT DISKLOG
JZ LOGOFF ; Then check for exit file
ENDIF ; NOT DISKLOG
;
IF DISKLOG
JZ DROPIT ; Hang up on the twit
ENDIF ; DISKLOG
;
CPI MSGKEY
RNZ
;
;
; Message from Sysop
;
LXI H,MFSMSG ; SYSOP message
CALL PRINTB ; Tell caller you want to say something
;
SYSML: CALL VCONIN ; Get key from Sysop
CPI XITKEY ; If exit key, exit loop
JZ SYSMX
MOV C,A ; Else echo to console and modem
PUSH PSW
CALL MOUTPUT
POP PSW
CPI 'H'-'@' ; If BS, do BS/SP/BS
JZ SYSMBS
CPI CR ; If CR, do CRLF
JZ SYSMCR
JMP SYSML
;
SYSMCR: MVI C,LF ; Do linefeed after CR
JMP SYSECH
;
SYSMBS: MVI C,' '
CALL MOUTPUT
MVI C,'H'-'@'
;
SYSECH: CALL MOUTPUT
JMP SYSML
;
SYSMX: MVI C,CR ; Do crlf
CALL MOUTPUT
MVI C,LF
CALL MOUTPUT
CALL MDINP
CALL MDINP ; Clear caller junk first
MVI A,CR ; Return with c/r for buffer
RET
;.....
;
;
; System Going down
;
SYSDOWN:LXI H,SGDMSG ; System going down message
CALL PRINTB ; Send this message
;
IF TIMEON
CALL TCHECK ; Calculate current time-on-system
LDA TON ; Fetch it
ADI DOWNMIN ; Give him this much longer
STA MXTIME ; And BYE will log him off
ENDIF ; TIMEON
;
MVI A,CR ; Return with CR for buffer
RET
;.....
;
LCDOIT: LXI H,LCDMSG
CALL PRINTL ; Show sysop it's flagged
MVI A,07FH
STA LCDFLG ; Set the flag
RET
;
;
; Toggle bell
;
BELLTOG:LDA BELLON ; Get bell status
ORA A
MVI A,0FFH ; Prepare for on
LXI H,BELMON
JZ BELLT1 ; Go turn bell on
XRA A ; Else turn bell off
LXI H,BELMOFF
;
BELLT1: STA BELLON
;
IF LMBELL
ORA A
JZ BELLT2 ; We will toggle whatever we just stored
XRA A
JMP BELLT3
BELLT2: MVI A,0FFH
;
BELLT3: STA KILBEL ; For MBBS/RBBS etal
ENDIF ; LMBELL
;
CALL PRINTL ; Print status message locally
MVI A,07FH ; DEL for buffer
RET
;.....
;
;
ULTIME: XRA A
STA MXTIME ; Give current caller unlimited time
MVI A,0FFH
STA LCPTR ; Also enable all the flag bits
LXI H,ULTMSG
CALL PRINTL ; So Sysop will know
MVI A,CR ; C/R for buffer
RET
;
;
; Toggle blankout
;
BLNKTOG:LDA MDMOFF
ORA A ; If zero, make 0FFH
;
IF ZCPR2 OR ZCPR3
JZ DUSET ; Store Sysops d/u values
CALL RETDU ; Restore normal d/u values
ENDIF ; ZCPR2 OR ZCPR3
;
IF (NOT ZCPR2) AND (NOT ZCPR3)
MVI A,0FFH ; (we do not use CMA, because MDMOFF
LXI H,SCRMOFF
JZ BLNKT1 ; Could equal a different value like 1)
XRA A ; If not zero, make it zero
LXI H,SCRMON
ENDIF ; NOT ZCPR2 AND NOT ZCPR3
;
BLNKT1: STA MDMOFF
;
IF ZCPR2 OR ZCPR3
STA WHEEL ; Set wheel for Sysop
ENDIF ; ZCPR2 OR ZCPR3
;
CALL PRINTL
MVI A,CR ; Return with cr for buffer
RET
;.....
;
;
DUSET: IF ZCPR2 OR ZCPR3
MVI A,SYSUSR+1 ; Sysops maxuser
STA MAXUSER ; To low memory
MVI A,SYSDRV-1 ; Sysops maxdriv
STA MAXDRIV ; To low memory
LDA LCPTR
STA CDOFF ; Save flag register
ENDIF ; ZCPR2 OR ZCPR3
;
IF CHGPATH
CALL SYSPAT ; Setup Sysops path
ENDIF ; CHGPATH
;
IF ZCPR2 OR ZCPR3
MVI A,0FFH ; Wheel on, modem off
STA LCPTR ; Enable all options
LXI H,SCRMOFF ; Correct message
JMP BLNKT1
;
RETDU: LDA MXUSR ; Callers allowed maxuser
INR A
STA MAXUSER ; To low memory
LDA MXDRV ; Callers allowed maxdriv
DCR A
STA MAXDRIV ; To low memory
LDA CDOFF
STA LCPTR ; Restore flag register
ENDIF ; ZCPR2 OR ZCPR3
;
IF CHGPATH
CALL REMPAT ; Setup remote users path
ENDIF ; CHGPATH
;
IF ZCPR2 OR ZCPR3
XRA A ; Wheel off, modem on
LXI H,SCRMON ; Correct message
RET
ENDIF ; ZCPR2 OR ZCPR3
;
IF NO25TH OR MBBS
WHOSIT: LXI H,CRMSG ; Turn up a fresh line
CALL PRINTL
LXI H,LCHEAD ; Print customized header (if any)
CALL PRINTL
LXI H,LCDATA
CALL PRINTL ; Show Sysop lastcaller data
LXI H,CRMSG
CALL PRINTL ; New line for neatness
MVI A,07FH ; DEL for buffer
RET
ENDIF ; NO25TH OR MBBS
;.....
;
;
IF TIMEON
DTIME: CALL TCHECK ; Read time
LXI H,LFMSG
CALL PRINTL
LDA MXTIME
ORA A
JZ DTIME1 ; Unlimited time
LXI H,TLNMSG ; Else print time-left...
ENDIF ; TIMEON
;
IF TIMEON AND (ZCPR2 OR ZCPR3)
LDA WHEEL
ORA A
JNZ DTIME1 ; Unlimited time
ENDIF ; TIMEON AND ZCPR2 OR ZCPR3
;
IF TIMEON
JMP DTIME2
DTIME1: LXI H,TONMSG
DTIME2: CALL PRINTL ; Print time-on or time-left-on system
LXI H,LFMSG
CALL PRINTL
MVI A,07FH ; DEL for buffer
RET
ENDIF ; TIMEON
;.....
;
;
CLEARIT:LXI H,CLRSEQ
CALL PRINTL ; Clear local screen
MVI A,LF
RET ; LF for buffer
;
IF LEADIN
FKEXIT: POP PSW
RET
ENDIF ; LEADIN
;.....
;
; end of function key routines
;------------------------------------------------------------------------
;
; BYE's BDOS interceptor (See BYE5.DOC for more information)
;
REALBD: JMP 0 ; Will be filled in to pnt to REAL BDOS
;
BYERSX:
;
IF DISKLOG
MOV A,C
CPI 15 ; Is it file open?
JNZ NOT15B
LDA LOGTOG ; Are we to toggle log file?
ORA A
JZ NOT15
PUSH D
CALL LOGFLP ; Open/close log file
POP D
XRA A
STA LOGTOG ; Reset toggle
JMP NOT15A
NOT15:
LDA DSKLOG ; Get log status
ORA A
JZ NOT15A ; Skip if not open
PUSH D ; Save callers FCB address
CALL SETLUS ; Set up the log environment
LXI D,LOGFCB
MVI C,16
CALL REALBD ; Update directory for log file
CALL CLRLUS ; Back to normal environment
POP D ; Restore callers FCB address
NOT15A:
MVI C,15 ; Restore open function code
NOT15B:
CALL STBDOS ; Set bdos call in progress flag
LDA DSKLOG
ORA A ; Is log on?
MOV A,C ; Get the function
JZ NOLOGTEST ; Skip tests if log is off
ENDIF ; DISKLOG
;
IF DISKLOG AND CPM3
CPI 98 ; Is it free blocks (only called by CCP)
JNZ NOT98
CALL SETLUS ; Set up log file environment
LXI D,LOGFCB
MVI C,16
CALL REALBD ; Update directory entry for file
CALL CLRLUS ; Return to normal environment
MVI C,98
JMP REALBD ; And on to BDOS
NOT98:
CPI 13 ; Is it disk reset?
JNZ NOT13
LXI D,80H
MVI C,26
CALL REALBD ; First set DMA to default
MVI E,0
MVI C,14
CALL REALBD ; Next select disk A:
LXI D,0FFFFH ; Reset all drives
MVI C,37
MOV A,C
NOT13:
CPI 37 ; Is it reset drives?
JNZ NOT37
MOV A,E
ANI 0FEH ; Do not reset drive A:
MOV E,A
JMP REALBD
NOT37:
ENDIF ; DISKLOG AND CPM3
;
IF DISKLOG AND (NOT CPM3)
CPI 13 ; Is it Disk reset?
JNZ NOT13
CALL SETLUS ; Set up log file environment
LXI D,LOGFCB
MVI C,16
CALL REALBD ; Update directory entry for file
CALL CLRLUS ; Return to normal environment
MVI C,13
JMP REALBD ; And on to BDOS
NOT13:
ENDIF ; DISKLOG AND NOT CPM3
;
IF DISKLOG
CPI 1 ; Console input?
JNZ NOT1
CALL REALBD ; Get the char
JMP HARDWR ; And on to log write routine
NOT1:
CPI 6 ; Direct console I/O?
JNZ NOT6
MOV A,E ; Get direct console I/O function
INR A ; Only intercept 0FFh
JNZ REALBD
CALL REALBD ; Get the char
ORA A ; Anything there?
RZ ; Back to caller if nothing
;
HARDWR: ; Save char in log file
CALL STKNEW ; Switch to local stack
PUSH PSW
ANI 7FH
CALL WRBYTE ; Write the character
CPI CR ; Is it return?
JNZ HARRET
MVI A,LF ; If CR, must also put LF in log file
CALL WRBYTE
HARRET:
POP PSW ; Restore original character
RET
;
NOT6:
CPI 10 ; Is it input console buffer?
JNZ NOLOGTEST
PUSH D ; Save address of buffer
CALL REALBD ; Fill the buffer
POP H
INX H ; Point to length
MOV A,M ; Get length
ORA A
RZ ; Return if nothing there
CALL STKNEW ; Switch to local stack
PUSH H
CALL WRTTIM ; Time stamp the line
POP H
MOV B,M ; Get length
INX H
B10LOP: ; Loop to write the log file
MOV A,M
CALL WRBYTE ; Send a byte to log
INX H
DCR B
JNZ B10LOP
JMP WRCRLF ; Exit with final CRLF
;
NOLOGTEST:
ENDIF ; DISKLOG
;
IF DISKLOG AND (NOT CPM3)
CPI 26 ; Is it set DMA?
JNZ NOTDMA
XCHG
SHLD OLDDMA ; Keep a copy of current DMA
XCHG
JMP REALBD
NOTDMA:
ENDIF ; DISKLOG AND NOT CPM3
;
MOV A,C ; BDOS doesn't care if we use 'A'
CPI 32 ; Is it USER command?
JZ TSTUSR
CPI LOCMD ; Is it less than lowest BYE command?
JC REALBD
CPI HICMD+1 ; Is it higher than the highest BYE
; Command?
JNC REALBD
;
;
; Ok, it's one of our commands, Let's handle it
;
SUI LOCMD ; Commands now range from 0..highcommand
PUSH D
MOV E,A ; Save copy of command in A
ADD A ; A=2*A
ADD E ; A=3*A 3x offset for each vector
MOV E,A ; Make command offset 16-bits
MVI D,0 ; DE = offset into table
LXI H,RSXTBL
DAD D ; HL points to entry in RSXTBL now
POP D
MOV A,E ; Generalized movement of input data
PCHL ; Jump to entry in rsx table
;
RSXTBL: JMP MDINST ; Get modem input status 61
JMP MDOUTST ; Get modem output status 62
JMP MDOUTP ; Output character to modem 63
JMP MDINP ; Input character from modem 64
JMP MDCARCK ; Get modem carrier status 65
JMP CONSTAT ; Get console input status 66
JMP CONIN ; Get console input character 67
JMP RCONOT ; Send character to console 68
JMP RMXDRV ; Set/get maximum drive 69
JMP RMXUSR ; Set/get maximum user area 70
JMP RMTOUT ; Set/get timeout value 71
JMP RMNULL ; Set/get nulls 72
JMP RMULC ; Set upper/lower case flag 73
JMP RMLFM ; Set line feed mask 74
JMP RMWRT ; Set/get wrtloc flag 75
JMP RMHDR ; Set/get hardon flag 76
JMP RMOFF ; Set/get mdmoff flag 77
JMP RMBELL ; Set/get console bell flag 78
JMP RMRTC ; Call TCHECK & return TON & RTC address 79
JMP RMLCBF ; Return LC buffer address 80
JMP RMMXT ; Set/get maximum time on system 81
JMP RMLTIM ; Set login time 82
JMP RMTOS ; Print TOS message to caller/Sysop 83
JMP SRUDEF ; SubRoutine U, the user DEFines 84
JMP RMXLCP ; Set/get LCPTR. When a user is logged 85
; In, LCPTR is a bit mapped status
; Register. If no user is logged in,
; LCPTR contains previous callers Timeon
JMP LOGSTAT ; Set/get log open status 86
JMP LOGPUT ; Write a string into log file 87
JMP IMDONE ; Hangup phone and return to calling pgm 88
JMP BEEPTOG ; Enable/disable inactivity beep flag
;
;
; BYE existance test
;
TSTUSR: MOV A,E ; Get E register value
CPI 241 ; Special call for extended BDOS?
JNZ REALBD ; No, was for normal BDOS
MVI A,77 ; Was for us, say we're here
RET
;
RCONOT: MOV C,E ; Get byte to send
JMP VCONOUT
;
RMXDRV: LXI H,MXDRV ; Set/get maximum drive
JMP SETGET1
;
RMXUSR: LXI H,MXUSR ; Set/get maximum user area
JMP SETGET1
;
RMNULL: LXI H,NULLS ; Set/get nulls
JMP SETGET1
;
RMTOUT: LXI H,TOVAL ; Set/get timeout value
JMP SETGET1
;
RMULC: LXI H,ULCSW ; Set/get upper-lowercase flag
JMP SETGET1
;
RMLFM: LXI H,LFEEDS ; Set/get line-feed mask
JMP SETGET2
;
RMHDR: LXI H,HARDON ; Set/get hard-log
JMP SETGET2
;
RMWRT: LXI H,WRTLOC ; Set/get RBBS WRTLOC flag
JMP SETGET2
;
RMOFF: LXI H,MDMOFF ; Set/get modem-off flag
JMP SETGET2
;
RMBELL: LXI H,BELLON ; Set/get console-bell flag
JMP SETGET2
;
BEEPTOG:
LXI H,BEEPFL ; Enable/disable inactivity beep flag
JMP SETGET2 ; for ZMODEM download <6lj/rmj>
;
RMRTC: IF TIMEON
CALL TCHECK ; TCHECK returns TON with/without clock
ENDIF ; TIMEON
;
IF CLOCK AND (NOT TIMEON)
CALL TIME ; In case caller just wants time
ENDIF ; CLOCK AND NOT TIMEON
;
LDA TON
LXI H,RTCBUF ; Return address of RTC buffer
RET
;
RMXLCP: LXI H,LCPTR ; Address of LCPTR
INR A ; If (255), return current value
JZ SGET1 ; So do it
MOV M,D ; If (A)<>255, store (D) in LCPTR (0-255)
RET
;
RMLCBF: LXI H,LCDATA ; Return address of LC data buffer
RET
;
RMMXT: LXI H,MXTIME ; Set/get maximum time allowed on system
JMP SETGET1
;
RMLTIM: STA LMIN ; Set login time
MOV A,D
STA LHOUR
RET
;
RMTOS: IF TIMEON ; Only do this if we can..otherwise RET
CALL TCHECK ; Set time in message
LDA MXTIME
ORA A
JZ RMTOS1 ; Unlimited time
LXI H,TLNMSG ; Else print time-left...
ENDIF ; TIMEON
;
IF TIMEON AND (ZCPR2 OR ZCPR3)
LDA WHEEL
ORA A
JNZ RMTOS1 ; Unlimited time
ENDIF ; TIMEON AND ZCPR2 OR ZCPR3
;
IF TIMEON
JMP RMTOS2
RMTOS1: LXI H,TONMSG
RMTOS2: CALL PRINTB ; Print it
ENDIF ; TIMEON
RET
;.....
;
;
; SETGET1 - if A=0..254 then poke value with A
; - if A=255 then return with current value
;
SETGET1:INR A ; If A was 255, Z flag will now be set
JZ SGET1 ; We want to get current value
DCR A
MOV M,A ; No, set current value
RET
;
SGET1: MOV A,M ; Return with current value in A
RET
;.....
;
;
; SETGET2 - if A=0 then poke value with 0
; - if A=1 then poke value with 255
; - if A=255 then return with current value
;
SETGET2:INR A ; If A was 255, Z flag will now be set
JZ SGET1 ; We want to get current value
DCR A ; If it's zero, then poke a zero
JZ SGET2W
MVI A,255 ; Else poke a 255
;
SGET2W: MOV M,A
RET
;.....
;
;
;-----------------------------------------------------------------------
;
CONIN: PUSH B
PUSH D
PUSH H
CALL VCONIN
CALL CKFUNC
POP H
POP D
POP B
RET
;.....
;
;
;-----------------------------------------------------------------------
;
CONOUT: PUSH B
PUSH D
PUSH H
MOV A,C
ANI 07FH
CNZ VCONOUT ; Don't send nulls to local console
POP H
POP D
POP B
RET
;.....
;
;
;-----------------------------------------------------------------------
;
CONSTAT:PUSH B
PUSH D
PUSH H
CALL VCONSTAT
POP H
POP D
POP B
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; .1 sec delay routine
;
DELAY: PUSH B
LXI B,4167*MHZ ; Timing constant * clock MHz
;
DELAY1: DCX B
MOV A,B
ORA C
JNZ DELAY1
POP B
RET
;.....
;
;
; 1 millisecond delay routine
;
KDELAY: PUSH B
LXI B,42*MHZ ; Timing constant * clock MHz
JMP DELAY1
;.....
;
;
;-----------------------------------------------------------------------
;
; Here to exit to CP/M, first reset the Port/Modem to default status
;
BEXCPM: LXI H,BELMSG ; Sysop typed LCKEY so alert him that
CALL PRINTL ; The system is his
;
EXCPM: IF B5IM
CALL IMQUIT ; Send ATS0=0 or ATH1M0 but keep DTR high
ENDIF ; B5IM
;
IF NOT B5IM
CALL MDQUIT ; Exit with DTR low
ENDIF ; NOT B5IM
;
IF MOTOR
CALL DSKON ; Turn on drives
ENDIF ; MOTOR
;
IF DISKLOG
MVI E,0
CALL TSTHRD ; Make sure log file is closed
ENDIF ; DISKLOG
;
LHLD REALBD+1 ; Get real bdos vector
;
IF CPM3
SHLD STARTX+1 ; Restore for cpm3 exit
ENDIF ; CPM3
;
IF NOT CPM3
SHLD BDOS+1 ; Save it so CP/M doesn't crash
ENDIF ; NOT CPM3
;
IF ZCPR2 OR ZCPR3
MVI A,0FFH
STA WHEEL ; Restore wheel byte for SYSOP
MVI A,SYSUSR+1
STA MAXUSER ; And MAXUSR
MVI A,SYSDRV-1
STA MAXDRIV ; And MAXDRIV
ENDIF ; ZCPR2 OR ZCPR3
;
IF CHGPATH ; If external zcpr path
CALL SYSPAT ; Setup Sysop's path
ENDIF ; CHGPATH
;
IF ZCPR3
CALL DOZ3 ; ZCPR3 re-initialization
ENDIF ; ZCPR3
;
IF CPM3
CALL RSXCLR ; Unload this RSX
ENDIF ; CPM3
;
CALL UNPATCH ; And then...
MVI A,0C3H
STA 000H ; Reset in case running local
JMP 0000H ; Warm boot CP/M
;.....
;
;
; ZCPR3 command line buffer, shell stack, TCAP stuff
;
IF ZCPR3
DOZ3: LHLD Z3CL ; Z3CL is the address of the MCLB
MVI M,0
;
;
; Command line done, now do shell stack
;
LXI H,SHSTK ; SHSTK is the addr of the Shell Stack
CALL ZERO128
;
;
; Now initialize TCAP
;
LXI H,Z3ENV+128 ; Z3ENV is the address of the Environ-
CALL ZERO128 ; Ment Descriptor...the TCAP is the
; Second 128 bytes
;
;
; Also clean up message buffers
;
LXI H,Z3MSG ; Z3MSG is the addr of the msg buffers
MVI B,80
CALL ZEROM
RET
;.....
;
;
; Routine to zero memory blocks
;
ZERO128:MVI B,128
ENDIF ; ZCPR3
;
ZEROM: MVI M,0
INX H
DCR B
JNZ ZEROM
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; Loss of carrier test and drive/user validation
;
CARCK: IF LMBELL
LDA KILBEL
CMA
STA BELLON ; Counteract MBBS foolishness
ENDIF ; LMBELL
;
LDA MDMOFF
ORA A ; Known loss?
JNZ CARCK2 ; Yes, allow d/u check locally
CALL MDCARCK ; Carrier there?
JNZ CARCK2 ; Yep, go onto other checks...
PUSH B ; Preserve so we can use it
MVI B,CLOSS*10 ; Set for 'CLOSS' seconds
;
CARLP: CALL DELAY ; Wait .1 seconds
CALL MDCARCK ; Check for carrier
MOV A,B ; Get count back in a
POP B ; Fix stack in case all is ok
JNZ CARCK2 ; Got carrier, continue on
DCR A ; Count time down
STC ; In case this is the end of 'time'
RZ ; Return if timed out
;
PUSH B ; Preserve 'BC'
MOV B,A ; Get counter value in 'B'
JMP CARLP ; Keep checking
;
;
; Now test drive #'s and (if CP/M 2.x) user #'s to insure that maximums
; are not exceeded.
;
CARCK2: IF USEZCPR AND (ZCPR2 OR ZCPR3)
LDA MAXDRIV
INR A
STA MXDRV
LDA MAXUSER ; Get it from ZCPR/ZCMD
DCR A ; Drop it one
STA MXUSR ; Save it in bye
ENDIF ; USEZCPR
;
IF (NOT USEZCPR) AND (ZCPR2 OR ZCPR3)
LDA MXDRV ; Older versions did not do this if
DCR A ; Wheel was set -- BAD KARMA
STA MAXDRIV
LDA MXUSR ; Get it from BYE
INR A ; Bump it
STA MAXUSER ; Save it in ZCPR
ENDIF ; NOT USEZCPR
;
IF CHEKDU
LDA 0004H ; Check disk/user #
ANI 0FH ; Isolate drive
PUSH H ; Save 'HL'
LXI H,MXDRV ; Point to allowed # of drives
CMP M ; Valid drive?
JC CARCK3 ; Yes, skip this junk
LDA 0004H ; Get whole login byte
ANI 0F0H ; Retain user #
ORI WBDRIV ; And force drive to wbdriv
STA 0004H ; Update login byte
ENDIF ; CHEKDU
;
IF CPM3 AND CHEKDU
MVI A,WBDRIV ; Zero drive message
CALL SETDRIVE
ENDIF ; CPM3 AND CHEKDU
;
IF CHEKDU
LXI H,IDMSG ; Incorrect Drive Message
CALL PRINTB ; Tell user what he did
JMP 0000H ; Warm boot
;...
;
;
CARCK3: LDA 0004H ; Get login byte
ANI 0F0H ; Isolate user #
RRC ; Move to low bits
RRC
RRC
RRC
LXI H,MXUSR ; Point to maximum user number
CMP M ; Valid user #?
JC CARCK4 ; Yes, don't change
JZ CARCK4
LDA 0004H ; Get login byte again
ANI 0FH ; Keep drive, zero user area
STA 0004H ; Update login byte
ENDIF ; CHEKDU
;
IF CPM3 AND CHEKDU
XRA A ; Zero user request
CALL SETUSER
ENDIF ; CPM3 AND CHEKDU
;
IF CHEKDU
LXI H,IUMSG ; Invalid User message
CALL PRINTB ; Tell him what happened
JMP 0000H ; Warm boot
;...
;
;
CARCK4: POP H ; Restore 'HL'
ENDIF ; CHEKDU
;
ORA A
RET
;.....
;
;
;-----------------------------------------------------------------------
; print routines
;
; The following code has been modified to accomodate the automatic
; loader. (The loader may modify a constant, so all messages have been
; placed at the end of the program and just moved to high memory.)
;
; Print on both consoles ** USE ONLY IF IN PATCHED MODE **
;
PRINTB: PUSH B ; Save BC
PUSH PSW ; And status regs
;
PRBL: MOV C,M ; Get character
CALL MOUTPUT ; Output it
INX H ; Point to next character
MOV A,M ; Test for end of message
ORA A
JNZ PRBL
POP PSW ; Restore status regs
POP B ; Restore BC
RET
;.....
;
;
; Print locally only
;
PRINTL: PUSH B ; Save BC
PUSH PSW ; And status regs
;
IF RVIDEO
CALL MDCARCK ; Carrier on?
JZ PRLL ; No, skip reverse video sequence
PUSH H ; Save original string address
LXI H,RVIDON
CALL PRTREV ; Print reverse-on sequence
POP H ; Restore original string
ENDIF ; RVIDEO
;
PRLL: MOV C,M ; Get character
CALL CONOUT ; Output it
INX H ; Point to next character
MOV A,M ; Test for end of message
ORA A
JNZ PRLL
;
IF RVIDEO
CALL MDCARCK ; Carrier on?
LXI H,RVIDOFF
CNZ PRTREV ; Yes, send the reverse-off sequence
ENDIF ; RVIDEO
;
POP PSW ; Restore status regs
POP B ; Restore BC
RET
;
IF RVIDEO
PRTREV: MOV C,M
CALL CONOUT ; Send the character
INX H
MOV A,M
ORA A ; End of string?
RZ ; Yes, exit
JMP PRTREV ; Else keep sending
ENDIF ; RVIDEO
;
;.....
;
;
;-----------------------------------------------------------------------
;
LISTOUT:PUSH B
PUSH D
PUSH H
PUSH PSW
;
IF NOT CPM3
CALL BDCHEK
ENDIF ; NOT CPM3
;
MOV C,A
CALL VLISTOUT
POP PSW
POP H
POP D
POP B
RET
;.....
;
;
;---------------------------------------------------------------------------
IF DISKLOG
;
;
; Toggle disk log on/off
;
;
LOGFLP: LDA BDOSFL
ORA A ; Are we in BDOS function?
JZ LOGFLP1 ; Ok to proceed if not
STA LOGTOG ; Otherwise, save toggle flag
MVI A,07FH ; DEL for buffer
RET ; And exit
LOGFLP1:
CALL STKNEW ; Switch to local stack
LXI H,DSKLOG
MOV A,M
ORA A ; What is the status?
JZ OPENLOG
XRA A
JP CLSHRD ; Go and close it
OPENLOG:
LXI H,DSKLOG
OPNHRD:
INR M
DCR M
MVI A,07FH
RNZ ; Return if already open
ORI 0FFH
MOV M,A ; Set the flag
CALL OPNLOG ; Open the log file
LXI H,OPNMSG
CALL PRINTL ; Tell sysop log file is open
MVI A,07FH ; DEL for buffer
RET
TSTHRD: ; Close/open request via BDOS
MOV A,E ; Get request state
LXI H,DSKLOG
ORA M ; Both zero?
RZ ; Return if already closed
CALL STKNEW ; Switch to local stack
MOV A,E
ORA A
JNZ OPNHRD ; Jump if to open
CLSHRD:
MOV M,A ; Reset log flag
CALL WRCRLF ; Write final cr,lf
CALL CLSLOG ; Close the log file
LXI H,CLSMSG
CALL PRINTL ; Tell sysop log file is closed
MVI A,07FH ; DEL for buffer
RET
;.....
;
;
; Log file routines
;
CLSLOG: ; Close the log file
MVI A,26
CALL WRBY ; Put EOF into log file
CALL WRITE ; Write the last sector
CALL SETLUS ; Set to log user
LXI D,LOGFCB
MVI C,16
CALL REALBD ; Close the log file
JMP CLRLUS ; Reset current user number
;
OPNLOG: ; Open the log file
CALL SETLUS ; Set to log user
XRA A
STA WOFFSET ; Init log write offset
LXI H,LOGFCB+12
LXI D,LOGFCB+13
MVI M,0
MVI B,23
CALL MOVE ; Clear SYS.LOG FCB to zeros
LXI D,LOGFCB
MVI C,15
CALL REALBD ; Attempt to open SYS.LOG file
INR A ; Any errors ?
JNZ NOLOGMAKE ; No need to create new file if exists
LXI D,LOGFCB
MVI C,22
CALL REALBD ; Create new SYS.LOG file
NOLOGMAKE:
LXI D,LOGFCB
MVI C,35
CALL REALBD ; Determine SYS.LOG file size
LHLD LOGFCB+33 ; Get the file size
MOV A,H
ORA L ; Is it zero?
JZ CLRLUS ; All set up if empty
DCX H ; Point to last record
SHLD LOGFCB+33 ; Put it back
LXI D,LOGFCB
MVI C,33
CALL REALBD ; Read the last record
LXI B,128 ; Init offset and counter
MVI A,26 ; Just a CTRL-Z (eof marker)
LXI H,RECORD ; Point to start of record
FINDEOF:
CMP M ; Is it EOF?
JZ FOUNDEOF
INX H
INR B
DCR C
JNZ FINDEOF ; Loop through last record
DCR B ; If not found, assume end of record
FOUNDEOF:
LXI H,WOFFSET ; Point to SYS.LOG write offset
MOV M,B ; Save write offset
JMP CLRLUS
ENDIF ; DISKLOG
;
IF DISKLOG AND CPM3
SETLUS: ; Set to log file user
LHLD SCBBASE
MVI L,0E0H
MOV A,M ; Get current user number
LXI D,OLDLUS
STAX D ; Save it
MVI M,LOGUSR ; Set to log user
MVI L,0E6H
INX D
MOV A,M ; Get current multi-sector count
MVI M,1 ; Set multi-sector count to 1
STAX D ; Save old multi-sector count
MVI L,0D8H ; Point to current DMA
INX D
MOV A,M ; Get low DMA
STAX D
INR L
INX D
MOV A,M ; Get high DMA
STAX D
LXI D,RECORD
MVI C,26
JMP REALBD ; Set DMA and return via BDOS
;
CLRLUS: ; Return to current user #
LHLD SCBBASE
MVI L,0E0H
LXI D,OLDLUS ; Point to save area
LDAX D ; Get old user #
MOV M,A ; Restore it
MVI L,0E6H
INX D
LDAX D ; Get old multi-sector count
MOV M,A ; Restore it
INX D
XCHG
MOV E,M ; Get old DMA low
INX H
MOV D,M ; Get old DMA high
MVI C,26
JMP REALBD ; Set old DMA and return via BDOS
ENDIF ; DISKLOG AND CPM3
;
IF DISKLOG AND (NOT CPM3)
SETLUS: ; Set up Log file environment
MVI E,255
MVI C,32
CALL REALBD ; Get current user number
STA OLDLUS ; Save it
MVI E,LOGUSR
MVI C,32
CALL REALBD
LXI D,RECORD
MVI C,26
JMP REALBD ; Set the DMA and return via BDOS
;
CLRLUS: ; Restore current environment
LDA OLDLUS ; Get old user number
MOV E,A
MVI C,32
CALL REALBD ; Restore old user number
LHLD OLDDMA ; Get old DMA address
XCHG
MVI C,26
JMP REALBD ; Set the old DMA and return via BDOS
ENDIF ; DISKLOG AND NOT CPM3
;
IF DISKLOG
ADDHLA:
ADD L
MOV L,A
RNC
INR H
RET
;
WRBYTE: ; Write a byte to log file
PUSH H
PUSH D
PUSH B
PUSH PSW
CPI ' ' ; Is it printable?
JNC WROK ; Jump if ok
CPI CR ; CR ?
JZ WROK
CPI LF ; LF ?
JZ WROK
CPI 8 ; BACK SPACE ?
JZ WROK
MVI A,'^'
CALL WRBY ; Write control char prefix
POP PSW
PUSH PSW
ADI 40H ; Make it printable
WROK:
CALL WRBY
POP PSW
POP B
POP D
POP H
RET
;
WRBY:
PUSH PSW
LDA WOFFSET ; Get write offset
LXI H,RECORD
CALL ADDHLA ; Form address
POP PSW ; Restore char
MOV M,A ; Put it in buffer
LXI H,WOFFSET
MOV A,M
INR A ; Bump offset
CM WRITE ; Write it out if buffer full
MOV M,A ; Save offset
RET
;
WRITE: ; Write a sector to log file
LDA WOFFSET
ORA A ; Is it empty?
RZ ; Return if nothing to write
PUSH H
CALL SETLUS ; Set up log file environment
LXI D,LOGFCB
MVI C,21
CALL REALBD ; Write the sector
CALL CLRLUS ; Restore environment
XRA A ; Set offset to 0
POP H
RET
;
WRCRLF: ; Write a cr, lf to log file
MVI A,CR
CALL WRBYTE
MVI A,LF
JMP WRBYTE
;
WRTMSG: ; Write message at [HL] to log file
LDA DSKLOG
ORA A
RZ ; Do nothing if no log
PUSH H
CALL WRTTIM ; Time stamp the message
POP H
WRTMS1:
MOV A,M
ORA A
JZ WRCRLF ; If at end, exit through crlf
CALL WRBYTE ; Write the byte
INX H
JMP WRTMS1
;
WRTTIM: ; Time stamp the log file
ENDIF ; DISKLOG
;
IF DISKLOG AND CLOCK
CALL TIME ; Update the time
ENDIF ; DISKLOG AND CLOCK
;
IF DISKLOG
LXI H,RTCBUF ; Point to hour
CALL WRTA
MVI A,':'
CALL WRBYTE
INX H ; Point to minute
CALL WRTA
MVI A,' '
JMP WRBYTE ; Write final space
;
WRTA: ; Write time (BCD) to log file
MOV A,M
RAR
RAR
RAR
RAR
CALL WRTHEX ; Write first BCD digit
MOV A,M
WRTHEX:
ANI 0FH ; Isolate digit
ADI '0' ; Convert to ascii
JMP WRBYTE ; Exit through write byte
;....
;
; Set the BDOS call in progress flag so that bios calls do not write to
; log file as well.
;
STBDOS:
MVI A,0FFH
STA BDOSFL ; Set bdos call in progress flag
POP H ; Retrieve return address
SHLD CALLIN+1 ; Modify call instruction
CALLIN:
CALL 0 ; Return to caller
PUSH PSW ; Return from caller gets us here
XRA A
STA BDOSFL ; Reset bdos call in progress flag
POP PSW
RET
;
STKNEW: ; Switch to local stack for log write
SHLD HLSAVE ; Save HL
POP H ; Retrieve return address
SHLD USRCAL+1 ; Modify call instruction
LXI H,0
DAD SP
SHLD OLDSP ; Save old stack
LXI SP,NEWSTK ; Set up new stack
LHLD HLSAVE ; Restore HL
USRCAL:
CALL 0 ; Back to caller
LXI SP,0 ; Restore old stack
OLDSP EQU $-2
RET
;.....
;
; Function 86 - LOGSTAT
; E = 0FFH Return log status in A
; E = 1 Turn log on
; E = 0 Turn log off
; If the equate DISKLOG is NO, A = 77 on return from this call
;
LOGSTAT:
MOV A,E
INR A ; Test for FFH
JNZ TSTHRD ; Go turn log on/off
LDA DSKLOG ; Get log status
ORA A
RZ
ORI 0FFH
RET
;.....
;
; Function 87 - LOGPUT Write a string at [DE] to log file
;
LOGPUT:
CALL STKNEW ; Switch to local stack
XCHG ; String address into HL
JMP WRTMSG ; And go write it out
ENDIF ; DISKLOG
;
IF NOT DISKLOG
LOGSTAT:
LOGPUT:
MVI A,77 ; Say disklog doesn't exist
RET
ENDIF ; NOT DISKLOG
;
IF DISKLOG
PUTSL:
MVI A,'/'
STAX D
INX D
RET
;
DATEMSG:
MOV A,M
RAR
RAR
RAR
RAR
CALL PUTDATE
MOV A,M
INX H
PUTDATE:
ANI 0FH
ADI '0'
STAX D
INX D
RET
ENDIF ; DISKLOG
;
;....
;
;-----------------------------------------------------------------------
; .COM file routine
;
; Routine to load the .COM file
;
LODCOM: IF COMFILE
MVI C,SELDSK
MVI E,COMDRV-'A' ; Select drive with .COM file on
CALL BDOS
MVI C,SETUSR ; Set CP/M user area function
MVI E,COMUSR ; Location of our COMFILE
CALL BDOS
ENDIF ; COMFILE
;
IF MSGFIL ; Routine to load message file handler
LDA 000H
CPI 0C2H ; Flag that says KMD RM'ed a file
JNZ NOMSGF ; No message file uploaded
XRA A
STA MSGFCB ; Prep the fcb
LXI H,MSGFCB
SHLD CURRFCB
LXI H,MSGFCB+12
MVI B,21
CALL ZEROM
LXI D,MSGFCB ; Ready to load it now
JMP LODCM2 ; So do it
;
NOMSGF: ENDIF ; MSGFIL
;
IF MBBS
LDA OPTION
CPI 'C' ; MBBS for comments, login otherwise
JNZ LODCM1 ; Load login
MVI C,SELDSK
MVI E,MBSDRV-'A'
CALL BDOS ; Select mbbs.com drive
MVI C,SETUSR
MVI E,MBSUSR
CALL BDOS ; Select mbbs.com user
XRA A
STA OPTION ; Clear option flag
STA FCB+1 ; And FCB to avoid loop
STA CM2FCB
LXI H,CM2FCB ; MBBS fcb
SHLD CURRFCB
LXI H,CM2FCB+12
MVI B,21
CALL ZEROM ; Clear rest of fcb
LXI D,CM2FCB
JMP LODCM2 ; Load MBBS
ENDIF ; MBBS
;
IF COMFILE
LODCM1: LXI H,COMFCB
SHLD CURRFCB
XRA A ; Initialize FCB
STA COMFCB
LXI H,COMFCB+12
MVI B,21
CALL ZEROM
LXI D,COMFCB
;
LODCM2: CALL OPENFIL
JZ ABORT
JMP LOADFIL
ENDIF ; COMFILE
;
LODEX: IF EXFILE
LXI H,EXITFCB
SHLD CURRFCB
LXI H,EXITFCB+12
MVI B,21
CALL ZEROM
LXI D,EXITFCB
CALL OPENFIL
JZ ABORT ; Cannot open file, finish BYE hangup
JMP LOADFIL
ENDIF ; EXFILE
;
IF TABBY
LODTBY: LXI H,TBYXFCB
SHLD CURRFCB
LXI H,TBYXFCB+12
MVI B,21
CALL ZEROM
LXI D,TBYXFCB
CALL OPENFIL
JZ ABORT ; Cannot open file, finish BYE hangup
ENDIF ; TABBY
;
;
; Now load the file
;
IF COMFILE OR EXFILE OR TABBY
LOADFIL:LHLD 6 ; Get top of memory
LXI D,-80H
DAD D
PUSH H ; Save on stack
LXI D,80H ; TPA-80H
LXI B,0 ; Keep a record counter
PUSH B ; Save counter
PUSH D ; And load address
;
GLOOP: POP D ; Get TPA address
LXI H,80H ; Point to next address to read to
DAD D ; HL has the address
POP B ; Increment the counter
;
;
; Check for load past top-of-memory
;
POP D ; Get (top-of-memory)
PUSH D ; Resave for next time
MOV A,E ; Subtract: (top) - (address)
SUB L
MOV A,D ; Only the carry needed
SBB H
JNC SIZEOK ; CY=better MOVCPM
LXI H,PTSMSG
JMP ERRXIT
;
SIZEOK: INX B
PUSH B
PUSH H ; Save TPA address
XCHG ; Align registers
MVI C,STDMA ; Tell BDOS where to put record
CALL BDOS
LHLD CURRFCB ; Point to aprropriate FCB
XCHG
MVI C,READ
CALL BDOS
ORA A
JZ GLOOP ; A=0 if more to read
POP B ; Unjunk stack
POP B ; This is our counter
POP H ; More junk on stack
MOV A,B ; Check for zero
ORA C
JZ ABORT ; We should have read something
LXI D,80H ; We did, reset DMA to 80H
MVI C,STDMA
CALL BDOS
LXI H,CFLMSG
CALL PRINTL
RET
;.....
;
;
ABORT: LXI H,CNFMSG
;
ERRXIT: CALL PRINTL
MVI A,0CDH ; Force logoff
STA 000H ; And system reset
JMP 000H ; Via warm boot trap
ENDIF ; COMFILE OR EXFILE OR TABBY
;.....
;
;
OPENFIL: IF CPM3
PUSH D ; Save FCB address
LXI D,0080H
MVI C,STDMA
CALL BDOS ; Set DMA to 0080H
POP D ; Get back pointer to FCB
PUSH D ; Save FCB pointer again
MVI C,SEARCH ; Search for first match
CALL BDOS
INR A ; Did a file match?
POP D
RZ ; No, return
PUSH D
DCR A ; A=directory code (0-3)
ADD A ; *2
ADD A ; *4
ADD A ; *8
ADD A ; *16
ADD A ; *32
MOV E,A
MVI D,0
LXI H,0080H ; Add (32*dir code) to default DMA
DAD D ; To find first match filename
POP D ; DE=FCB
PUSH D ; Save DE again
INX H ; Move HL past user # byte in buffer
INX D ; Move DE past drive # in FCB
MVI B,11
CALL MOVE ; Move name found to FCB
POP D ; And continue with the open
ENDIF ; CPM3
;
MVI C,OPEN ; Open file pointed to by 'DE'
CALL BDOS
INR A
RET
;.....
;
; end of .COM file routine
;-----------------------------------------------------------------------
;
; Boot trap - becomes disconnect if JMP at 0 has been altered
;
MBOOT: LDA OPTION
CPI 0FFH ; Local cp/m with BYE5 running?
JZ VWARMBT ; Yes, skip this check
;
LXI SP,STACK ; Ensure good stack
;
IF EXRET
LDA FCB+1
CPI 'r' ; Returning from an exit file?
JZ PREOFF ; Then prepare for next call
ENDIF ; EXRET
;
IF MSGFIL ; See if KMD RM'ed a file
LDA 0
CPI 0C2H ; Flag left by KMD?
JNZ MBOOT1 ; No, continue
LXI H,MSGMSG ; Let Sysop know what file is sought
CALL PRINTL
CALL LODCOM ; Try to load it
MVI A,0C3H ; Reset the flag
STA 000H
CALL 0100H ; Now run the message file handler
LXI SP,STACK ; Restore the stack
;
MBOOT1: ENDIF ; MSGFIL
;
IF CPM3
MVI B,0B3H ; Offset to CHAIN PROGRAM flag in SCB
CALL GETSCB ; Get byte from SCB
ANI 080H ; In the middle of a CHAIN PROGRAM now?
JNZ VWARMBT ; Yes, skip checks
ENDIF ; CPM3
;
IF (COMFILE OR EXFILE OR TABBY) AND (NOT PBBS)
LDA OPTION
CPI 'E' ; Return from local test?
JNZ MBOOT2 ; No, continue
MVI A,' '
STA FCB+1 ; Fool system
STA OPTION
CALL UNPATCH ; Yes, restore
ENDIF ; COMFILE OR EXFILE OR TABBY AND NOT PBBS
;
IF (EXFILE OR TABBY) AND (NOT (MBBS OR PBBS))
JMP LOGOFF ; Run exit file locally
ENDIF ; EXFILE AND NOT MBBS/PBBS
;
IF COMFILE AND (NOT PBBS)
JMP START0 ; And start fresh
ENDIF ; COMFILE AND NOT PBBS
;
MBOOT2: LDA 0 ; Look at opcode
CPI 0C3H ; Is it still a jmp?
;
IF MBBS
JNZ NORPTC ; Let login take over
ENDIF ; MBBS
;
IF NOT MBBS
JNZ LOGOFF ; Check for exit file
ENDIF ; NOT MBBS
;
IF NOT CPM3
CALL BDCHEK
ENDIF ; NOT CPM3
;
IF (NO25TH OR MBBS) AND READLC
LDA LCDATA ; See if lastcalr has been read
CPI ' ' ; Or data poked by a BBS, like MBBS
JNZ NO25EX ; Yes, skip this
XRA A ; Else, let's pick up the lastcalr file
STA FCBRNO ; Prepare FCB for lastcalr
LXI H,LCNAME
LXI D,FCB
MVI B,13
CALL MOVE ; Move rest of FCB
MVI C,0DH ; Reset disk and
CALL BDOS ; Set for default buffer
MVI C,SELDSK
MVI E,LCDRV-'A'
CALL BDOS ; Set drive
MVI C,SETUSR
MVI E,LCUSR
CALL BDOS ; And user
LXI D,FCB
CALL OPENFIL ; Open it
LXI H,LCMSG1
CZ PRINTL ; Error msg
JZ NO25EX ; No file available, exit
LXI D,FCB
MVI C,READ
CALL BDOS ; Read 1 record max
LXI H,LCMSG1
ORA A
CNZ PRINTL ; Say error
LXI H,80H
LXI D,LCDATA
MVI B,NO25BF ; Size of buffer
CALL MOVE ; Move data into bye's internal buffer
MVI B,NO25BF ; Max we will display
LXI H,LCDATA
;
NO25RD: MOV A,M
CPI 'Z'-'@' ; EOF?
JZ NO25ZD
CPI ','
CZ NO25SP ; Change commas and semicolons to spaces
CPI ';'
CZ NO25SP
CPI CR
CZ NO25SP ; Convert cr's and lf's to spaces
CPI LF
CZ NO25SP
DCR B
JZ NO25ZD
INX H ; Get next byte
JMP NO25RD
;
NO25ZD: XRA A
MOV M,A ; Set terminator for print routine
STA 04H
ENDIF ; READLC
;
IF NO25TH OR MBBS
NO25EX: CALL WHOSIT
ENDIF ; NO25TH OR MBBS
;
IF PRNTWB
LXI H,WBMSG
CALL PRINTB ; Print the following message:
ENDIF ; PRNTWB
;
IF TIMEON AND CLOCK AND PRNTOS
CALL RMTOS ; Display timeon
ENDIF ; TIMEON
;
JMP VWARMBT ; Go do a warm boot
;
IF (NO25TH OR MBBS) AND READLC
NO25SP: MVI A,' ' ; Space
MOV M,A ; To lcdata
RET
ENDIF ; NO25TH OR MBBS
;.....
;
;
;-----------------------------------------------------------------------
;
; Modem input function, checks local console first
;
MINPUT: IF NOT CPM3
CALL BDCHEK
ENDIF ; CPM3
;
XRA A ; Reset MSTAT no-activity flag
STA MSFLAG
MINP2:
; CALL CONSTAT ; Check for console input (bye510.fix)
; ORA A ; Got console input? (bye510.fix)
; JNZ CONIN ; Yep, get the console character(bye510.fix)
CALL MSTAT ; Nope, check for modem input
ORA A ; Got modem input?
JZ MINP2 ; Nope, loop again
CALL CONSTAT ; Check for console input (bye510.fix)
ORA A ; Got console input? (bye510.fix)
JNZ conin ; Yep, get the console character (bye510.fix)
MINP3: CALL MDINP ; Yep, get modem character
ANI 7FH ; Strip off any high bits
CPI FILT4 ; Ignore nulls
JZ MINP2
CPI FILT1 ; Ignore left braces
JZ MINP2
CPI FILT2 ; Was it a delete?
JZ MINP2 ; Filter this too
CPI FILT3 ; "`" causes TRS-80 glitch
JZ MINP2 ; So filter it too
;
IF ZCPR2 OR ZCPR3
MOV B,A ; Save byte in B
LDA WHEEL
ORA A
MOV A,B ; Get character back
JNZ MINP4 ; It's a wheel, don't trap ^P
ENDIF ; ZCPR2 OR ZCPR3
;
CPI 'P'-'@' ; Is it a ^P?
JZ MINP2 ; Ignore CTL-P unless wheel is set
;
MINP4: IF HARDLOG
PUSH B
MOV B,A ; Put a copy of the character in B
LDA HARDON ; If HARDON=0 then turn HARDLOG off (so
ORA A ; SYSOP does not waste paper while he
MOV A,B ; Playing ZORK from work.)
POP B
JZ NOLOG
CPI 20H
JNC MINP5
CPI CR
JNZ NOLOG
;
MINP5: CALL LISTOUT ; Echo on printer
CPI CR
JNZ NOLOG ; Return needs linefeed
MVI A,LF
CALL LISTOUT ; So send it
MVI A,CR ; Get back CR
ENDIF ; HARDLOG
;
NOLOG:
IF DISKLOG
MOV C,A
LDA DSKLOG
ORA A ; Is disk log on?
JZ NOHARD
LDA BDOSFL
ORA A ; Are we in a BDOS function call?
JNZ NOHARD
CALL STKNEW ; Switch to local stack
PUSH H
PUSH B
LDA TIMSFL ; Should we time stamp the log file?
ORA A
CNZ WRTTIM
POP B
POP H
MOV A,C
CALL WRBYTE ; Write out the byte
CPI CR ; Is it CR?
MVI A,LF
CZ WRBYTE ; Send LF if CR.
MVI A,0
JNZ HRDL1
DCR A ; Say that we have to time stamp next time
HRDL1:
STA TIMSFL
NOHARD:
MOV A,C
ENDIF ; DISKLOG
;
CPI 'C'-'@' ; Is it ^C?
RNZ ; No, pass it through
LDA 0 ; See if warm boot disabled
CPI 0C3H ; Jump means warm boot ok
MVI A,3 ; So return with a ^C
RZ
MVI A,CTRLC ; Else convert to different character
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; Modem output function
;
MOUTPUT: IF NOT CPM3
CALL BDCHEK
ENDIF ; NOT CPM3
;
XRA A
STA MSFLAG ; Reset no-activity flag
;
; If we already know carrier is lost, do not check for it again or loop
; trying to output.
;
IF COMFILE AND TIMEON AND CLOCK
LDA OPTION
CPI 'E' ; Running locally?
JNZ MONOTE ; No, continue
MOV A,C ; Check character
CPI LF ; One check per line
CZ TCHECK ; Keep clock updated, TCHECK saves
; Registers
MONOTE: ENDIF ; COMFILE AND TIMEON AND CLOCK
;
LDA MDMOFF ; Known loss of carrier?
ORA A
PUSH PSW
CNZ CONOUT ; Output to local only
POP PSW
RNZ ; Then exit
;
MOUTA: CALL CHECK ; Carrier still on?
CALL MDOUTST ; Check modem output status
JZ MOUTA
MOV A,C ; Get character
ANI 7FH ; Strip parity bit
RZ ; Don't output DEL to remote
CPI 60H ; Check for lower case
JC MOUTP2 ; Skip if not lower case
CPI 7FH ; Check for rubout
JZ MOUTP2
PUSH H
LXI H,ULCSW ; Subtract either 20H or nothing
SUB M
POP H
MOV C,A ; Force on local as well as remote
;
MOUTP2: CPI LF ; We have a toggle for line feeds
JNZ MOUTP3 ; Nope, not a LF
;
IF TIMEON
CALL TCHECK ; Update/check clock and timeon
ENDIF ; TIMEON
;
LDA LFEEDS ; Yes, see if we can send it...
ORA A ; Set flags
MVI A,0 ; Prepare with a null
JNZ MOUTP3 ; Nope, don't (instead, send a null)
MVI A,LF ; Yes, it's ok to send the line feed
;
MOUTP3: CALL MDOUTP ; Output character to modem
;
PUSH PSW ; Save character
CPI 'G'-'@' ; Is it a bell?
JNZ NOTBEL
LDA BELLON ; Get flag
ORA A
JZ ISBELL
;
NOTBEL: CALL CONOUT ; Send to regular BIOS
;
ISBELL: POP PSW ; Get character again
;
;
; Check for nulls
;
CPI LF ; Time for nulls?
RNZ ; No, return
;
;
; Send nulls if requested
;
LDA NULLS ; Get count
ORA A ; Any?
RZ ; No
PUSH B
MOV B,A ; Save count
;
NULLP: CALL MDOUTST ; Modem ready?
JZ NULLP
XRA A ; 00H is a null
CALL MDOUTP ; Send a null
DCR B ; Another?
JNZ NULLP ; Yes, loop
POP B
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; Move (HL) to (DE), length in (B)
;
MOVE: MOV A,M ; Get a byte
STAX D ; Put at new home
INX D ; Bump pointers
INX H
DCR B ; Decrement byte count
JNZ MOVE ; If more, do it
RET ; If not, return
;.....
;
;
;-----------------------------------------------------------------------
;
; Modem status test and no-activity timer routine
;
MSTAT: IF NOT CPM3
CALL BDCHEK ; Set 6 to safety
ENDIF ; NOT CPM3
;
LDA MDMOFF
ORA A
MVI A,0
JNZ MSTAT1
; RNZ ; Don't let remote input while modem is
; Muted
CALL CHECK ; Check for carrier lost
CALL MDINST ; Get modem input status
ORA A ; Character available?
JZ MSTAT1 ; Nope
MSTAT0:
PUSH PSW ; Yep, save return status
XRA A ; Clear no-activity flag
STA MSFLAG
POP PSW ; Restore return status
RET ; And return
;
MSTAT1: CALL CONSTAT ; Check local keyboard status (bye510.fix)
ORA A ; anything there? (bye510.fix)
JNZ MSTAT0 ; yep (bye510.fix)
LDA MSFLAG ; Get the no-activity flag
ORA A ; First time here?
MVI A,0FFH ; Reset virgin flag in all cases
STA MSFLAG
JNZ MSTAT3 ; Nope
LDA TOVAL ; Yep, get number of minutes to wait
MSTAT2: STA TOCNTM ; Initialize minutes counter
PUSH H ; Save registers
LXI H,42000 ; Initialize loop counter
SHLD TOCNT
POP H ; Restore registers
MSTAT3: CALL KDELAY ; Wait a millisecond
PUSH H ; Save registers
LHLD TOCNT ; Get the loop counter
DCX H ; Bump down
SHLD TOCNT ; And save
MOV A,H ; Done this loop?
ORA L
POP H ; Restore registers
JZ MSTAT4 ; Yep
XRA A ; Nope, clear return status
RET ; And return
MSTAT4: LDA BEEPFL ; If beeps allowed
ORA A ;
JNZ MSTAT5 ;
MVI A,'G'-'@' ; Beep the user
CALL MDOUTP ;
MSTAT5: ;
LDA TOCNTM ; Bump down minutes counter
DCR A ; Done?
JNZ MSTAT2 ; Nope
;
TMOUT: LXI H,ITOMSG ; Yep, caller time-out
LXI SP,STACK ; Restore stack
CALL PRINTB
CALL PATCH ; In case LUX was running
;
IF DISKLOG
XRA A
STA BDOSFL
LXI H,TMOMSG
CALL WRTMSG ; Put input timeout into log file
ENDIF ; DISKLOG
;
IF MBBS
JMP NORPTC ; Let mbbs/login log him off
ENDIF ; MBBS
;
IF NOT MBBS
JMP LOGOFF ; Check for exit file
ENDIF ; NOT MBBS
;.....
;
;
;-----------------------------------------------------------------------
;
; This is the jmp table which is copied on top of the one pointed to by
; location 1 in CP/M.
;
NEWJTBL:JMP MCBOOT ; Cold boot
JMP MBOOT ; Warm boot
JMP MSTAT ; Modem status test
JMP MINPUT ; Modem input routine
JMP MOUTPUT ; Modem output routine
;
IF (NOT HARDLOG) AND (NOT PRINTER)
RET ; Modem list device
NOP
NOP
RET ; Modem punch device
NOP
NOP
RET ; Modem reader device
NOP
NOP
ENDIF ; NOT HARDLOG AND NOT PRINTER
;.....
;
;-----------------------------------------------------------------------
;
IF MOTOR
DSKON: PUSH PSW ; Save 'A' and flags
MVI A,DISKON ; Turn on motors
OUT DISK
PUSH H ; Now, wait a long time
LXI H,0000
;
DSKLP: XTHL
XTHL
DCX H ; Count loop
MOV A,H ; Check if done?
ORA L
JNZ DSKLP
POP H ; Restore HL
POP PSW ; And 'A' and flags
RET
;
DSKOFF: PUSH PSW ; Save 'A' and flags
MVI A,DISKOFF ; Turn motors off
OUT DISK
POP PSW
RET
ENDIF ; MOTOR
;.....
;
;
;-----------------------------------------------------------------------
;
NWBCALL: IF LOSER
CALL WMSTRT ; Warm boot disk read
CALL PATCH ; Fix BIOS again after WMSTRT
ENDIF ; LOSER
;
IF NOT CPM3
CALL BDCHEK
ENDIF ; NOT CPM3
;
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; Patch in the new JMP table (saving the old)
;
PATCH: LDA PTFLAG
ORA A
JNZ SKPTH ; Save the original jump table only once
;
CALL TBLADDR ; HL= CP/M BIOS jump table
LXI D,VCOLDBT ; Point to save location
MVI B,24 ; Save all vectors
CALL MOVE ; Move it
LHLD VCONOUT+1 ; Get the original CONOUT address
SHLD COVECT ; Store for use with XMODEM programs
;
;
; Now move the new JMP table to CP/M
;
SKPTH: CALL TBLADDR ; HL= CP/M BIOS jump table
XCHG ; Move it to 'DE'
LXI H,NEWJTBL ; Point to new jump table
CALL MOVE ; Move it
MVI A,0FFH
STA PTFLAG
;
IF LOSER
LXI H,NWBCALL ; Set new warm boot call
SHLD WBCALL+1 ; Store the new address
ENDIF ; LOSER
;
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; PRNLOG is called to print out the BYE version # and USRLOG info. It
; can be called from outside the program, using the vector after MCBOOT.
;
PRNLOG: LXI H,VMSG
CALL PRINTL
CALL CALSUM
RET
;
CALSUM: LDA CWCAR ; Get 8 bit number
LXI H,ATMSN ; Address to store ascii
CALL DEC8 ; And convert to ascii
LXI H,ATMSG ; Print Callers with carrier detected
CALL PRINTL ; To local crt
;
IF B5IM ; Print # of voice calls
LDA VCNUM
LXI H,VCMSN ; Put ascii here
CALL DEC8
LXI H,VCMSG
CALL PRINTL
ENDIF ; B5IM
;
IF PWRQD
LDA NWPWD ; 8 bit counter
LXI H,NWMSD ; Put ascii here
CALL DEC8
LXI H,NWMSG ; Print callers who knew password
CALL PRINTL
ENDIF ; PWRQD
;
LXI H,LFMSG
CALL PRINTL ; Turn up a line
RET ; End of call summary
;.....
;
;
;-----------------------------------------------------------------------
;
; Readbyte routine - used to read the welcome file
;
IF WELFILE
RDBYTE: MOV A,H ; Time to read?
ORA A ; If at 100H, no read required
JZ NORD
;
;
; Have to read a sector
;
LXI D,FCB
MVI C,READ
CALL BDOS
ORA A ; Ok?
MVI A,1AH ; Fake up EOF
RNZ ; Return EOF if bad
LXI H,80H
;
NORD: MOV A,M ; Get character
INX H ; Point to next byte
RET
ENDIF ; WELFILE
;.....
;
;
;-----------------------------------------------------------------------
;
; Calculate HL=CP/M's jump table, B=length
;
TBLADDR:LHLD 1 ; Get BIOS pointer
DCX H ; Skip to cold boot
DCX H
DCX H
;
IF HARDLOG OR PRINTER ; Retain list device?
MVI B,15 ; Don't move lister jump
ENDIF ; HARDLOG
;
IF (NOT HARDLOG) AND (NOT PRINTER)
MVI B,24 ; Move all jumps
ENDIF ; NOT HARDLOG
;
RET
;.....
;
;
;-----------------------------------------------------------------------
;
; TSTBAUD attempts to read a CR, LF or CTL-C and returns with zero flag
; if the character read is one of these three.
;
IF NOT B5IM
TSTBAUD:CALL MDCARCK ; Check carrier first
JZ PREOFF ; Carrier is gone, start over
LDA CDOFF
INR A
STA CDOFF
CPI 60 ; Allow 1 minute for c/r detect
JZ PREOFF ; Hangup and start over
MVI D,20 ; Check for 2 sec for current baud rate
;
TSTB1: MVI B,1 ; At .1 sec intervals
PUSH D
CALL DELAY
CALL MDINST ; See if character available
ORA A
JZ TSTB2 ; None yet
CALL MDINP ; Yes, read the character
ANI 7FH
POP D ; Restore the stack
JMP TSTB3 ; And see if it is right character
;
TSTB2: POP D ; Restore DE
DCR D ; And decrement the count
MOV A,D
ORA A ; 2 sec's up??
JNZ TSTB1 ; No, try again
MVI A,0FFH ; Dummy character
;
TSTB3: CPI CR ; If a CR
RZ
CPI LF ; If a LF
RZ
CPI 'C'-40H ; If a CTL-C
;
IF TABBY AND (NOT B5IM)
RZ
CPI ' ' ; TABBY needs to know a space, for WHACKS
RZ
CPI TSYNC ; Was it an early TSYNC?
ENDIF ; TABBY AND NOT B5IM
;
RET ; Return with proper flags set
ENDIF ; NOT B5IM
;.....
;
;
;-----------------------------------------------------------------------
;
UNPATCH:CALL TBLADDR ; HL= CP/M BIOS jump table
XCHG ; Move to DE
LXI H,VCOLDBT ; Get saved table
CALL MOVE ; Move original table back
;
IF LOSER
LXI H,WMSTRT ; Load old call location
SHLD WBCALL+1 ; Restore old call
ENDIF ; LOSER
;
RET
;.....
;
;
;-----------------------------------------------------------------------
;
USRCHK: CALL PRNLOG ; Give info
LXI H,RS1MSG
CALL PRINTL ; Prompt to resume waiting for ring
;
PRNREL: CALL CONSTAT ; Reply?
ORA A
JZ PRNREL ; Wait until answered
CALL VCONIN ; Then get it
CPI 60H ; Lower case?
JC $+5 ; Skip conversion
SBI 20H ; Else make upper case
CPI 'E' ; Execute com file?
JZ USRUN ; Yes
CPI 'J' ; Jump to cp/m with BYE5 patched?
JZ JMPCPM ; Yes, exit to cp/m with BYE5 patched
CPI 'R' ; Is answer resume?
JZ PRNRES ; Go do it if so
LXI H,CRMSG
CALL PRINTL ; Turn up a fresh line
JNZ EXCPM ; And warm boot CP/M
;
PRNRES: LXI H,RS2MSG
CALL PRINTL ; Resume via BDOS after message
;
IF CLRSCR
CALL CLEARIT ; Clear the screen
ENDIF ; CLRSCR
;
RET
;
USRUN: MVI A,'E'
STA OPTION ; Fake it
JMP ERUN ; For Sysop
;
JMPCPM: IF B5IM
CALL IMQUIT ; Fix modem so it won't answer
ENDIF ; B5IM
;
IF NOT B5IM
CALL MDQUIT
ENDIF ; NOT B5IM
;
CALL PATCH ; Leave BYE5 attached
MVI A,0C3H
STA 000H ; Restore JMP instruction
MVI A,0FFH ; And set all the right flags
STA MDMOFF
STA OPTION
STA WRTLOC
;
IF ZCPR2 OR ZCPR3
STA WHEEL ; Including wheel byte for sysop
ENDIF ; ZCPR
;
JMP 000H ; Warmboot with BYE5 attached
;.....
;
;
;-----------------------------------------------------------------------
; WELCOME routine (note no extent used)
;
; Welcome to the system
;
WELCOME: IF CLOCK
CALL TIME ; Read current time
LDA CCHOUR ; And set
STA LHOUR ; The users
LDA CCMIN ; Login
STA LMIN ; Time for later use
ENDIF ; CLOCK
;
IF DISKLOG
CALL OPENLOG ; Make sure the log file is on
LXI H,RTCBUF+5
LXI D,CDAY
CALL DATEMSG ; Put month into message
CALL PUTSL ; Put a slash
CALL DATEMSG ; Put day into message
CALL PUTSL
LXI H,RTCBUF+4
CALL DATEMSG ; Put year into message
LDA MSPEED ; Get speed
ADI '0' ; Make it ascii
STA CONMS1 ; Stuff it into message
LXI H,CONMSG
CALL WRTMSG ; Put connect message into log file
ENDIF ; DISKLOG
;
IF TIMEON OR CLOCK
MVI A,MAXMIN ; Set number of minutes
STA MXTIME ; Into mxtime
XRA A
STA TCHKFG ; Show it's ok to check time
ENDIF ; TIMEON OR CLOCK
;
IF COMFILE
LDA OPTION
CPI 'E'
MVI A,0 ; Prepare default nulls in case
STA NULLS
JZ WELC1 ; Skip this if running locally
ENDIF ; COMFILE
;
LDA MSPEED
ADI 3 ; Value for nulls until BBS resets it
STA NULLS
;
LXI H,TERMSG
CALL PRINTB ; Let sysop/caller know you're online
; CALL MDINP ; COMMENTED OUT MARC NEWMAN 5/17/88
; CALL MDINP ; Clear garbage from modem input
;
IF NOT SKTERM
CALL MINPUT ; Accept any character, then proceed
ENDIF ; NOT SKTERM
;
IF TABBY ; If you are running Tabby
LXI B,TABCNT ; Number of tenths to check for TSYNC
NOTTBY: PUSH B
LDA CCHOUR
CPI NNHOUR ; Is it National Netmail Hour?
JNZ NOTNNH ; Nope
LXI H,NNHMSG
JMP PTBYMS
NOTNNH: LXI H,TBYMSG ; Tell them to wait or hit <ESCAPE>
PTBYMS: CALL PRINTB ; Print the message
POP B
WAITBY: CALL DELAY ; Wait 1/10th of a second
DCX B ; Decrement counter
MOV A,B
ORA C
JZ WELC1 ; Timed out, go run BBS
CALL MDINST ; And see if a character is waiting
ORA A ; See if we got anything
JZ WAITBY ; Nothing yet, go wait again
CALL MDINP ; Ok, let's get this character
CPI TSYNC ; Is it a TSYNC?
JZ GETTBY ; Time to load Tabby
CPI ESC ; Is it an Esacape?
JNZ NOTTBY ; No, go wait some more
LDA CCHOUR
CPI NNHOUR ; Is this National Netmail Hour?
JZ WAITBY
JMP WELC1
;
GETTBY: CALL UNPATCH ; Get rid of BYE
LHLD REALBD+1
SHLD BDOS+1 ; This completely gets rid of BYE
LXI H,CRMSG
CALL PRINTL
LXI H,RMAILNM
CALL PRINTL ; Print out the name of the com file
;
MVI C,SETUSR ; User area set call
MVI E,TBYUSER ; Set up user area
CALL BDOS
MVI C,SELDSK ; Drive set call
MVI E,TBYDRV-'A' ; Drive com file is on
CALL BDOS
MVI A,TBYUSER*010H+TBYDRV-'A' ;This makes SURE we are on
STA 0004H ; the right drive and user for $$$.sub files
;
LXI H,TBYFCB ; Address of RECMAIL.COM FCB
SHLD CURRFCB
LXI D,TBYFCB
CALL OPENFIL
JZ ABORT ; Error, abort
CALL LOADFIL
MVI A,0
STA 080H ; Make SURE Tabby sees a null command tail
MVI A,' '
STA 05DH
ENDIF ; Tabby
;
IF TABBY AND (ZCPR2 OR ZCPR3)
MVI A,0FFH ; Just in case a window opens while RECVMAIL
STA WHEEL ; runs, turn the wheel on so $$$.SUB can do
; important things like ERA and REN
ENDIF ; TABBY AND (ZCPR2 OR ZCPR3)
;
IF TABBY AND DISKLOG
MVI E,0
CALL TSTHRD ; Turn disk log off
ENDIF ; DISKLOG
;
IF TABBY
JMP 100H
ENDIF ; Tabby
;
;
WELC1: LXI H,CRMSG ; Carriage Return, Line Feed
CALL PRINTB ; Send this message
;
IF RSPEED
LDA OPTION
CPI 'E' ; Running locally?
JZ SPDOK ; Yes, skip this
XRA A ; Clear status
LDA MSPEED ; See what speed the user is at
SUI SPEED ; Is it acceptable?
JNC SPDOK ; Yes, continue
CALL TIME ; Get current time
MVI A,HOUR1 ; Start of prime-time
;
SPD01: LXI H,CCHOUR ; Point at current hour
CMP M ; Equal?
JZ SPDOFF ; Yes, dump him
INR A ; Check for
CPI HOUR2 ; End of prime-time
JZ SPDOK ; Not prime-time so let him on
CPI 24 ; Past midnight?
JNZ SPD01 ; No, continue
XRA A ; Yes set to 00 hour
JMP SPD01 ; And continue
;
SPDOFF: LXI H,OFFMSG ; Point at logoff message
CALL PRINTB ; And tell him why
JMP PREOFF ; Then log him off
ENDIF ; RSPEED
;
;
;
;
; Print the welcome file
;
SPDOK: IF WELFILE
LXI H,WELFILN ; Source
LXI D,FCB ; Destination
MVI B,13 ; Length
CALL MOVE ; Move the name
LXI D,80H ; Set DMA address to 80H
MVI C,STDMA
CALL BDOS
MVI C,SETUSR ; Set user number for WELCOME file
MVI E,WELUSR
CALL BDOS
;
;
; Open the WELCOME file
;
MVI C,SELDSK ; Select default drive for WELCOME file
MVI E,WELDRV-'A'
CALL BDOS
LXI D,FCB
CALL OPENFIL
;
;
; Did it exist?
;
JZ PASSINT ; No WELCOME file
;
;
; Got a file, type it
;
XRA A ; A=0
STA FCBRNO ; Zero record number
LXI H,100H ; Get initial buffer pointer
;
;
; Type the WELCOME file
;
WELTYPE:CALL RDBYTE ; Get a byte
CPI 'Z'-'@' ; EOF?
JZ PASSINT ; Yes, done
MOV C,A ; Setup for type
CALL MOUTPUT ; Type the character
CALL MSTAT ; Check for character typed
ORA A
JZ WELTYPE ; No, loop
CALL MINPUT ; Yes, get character
CPI 'C'-'@' ; Did user type a CTL-C to end listing?
JZ PASSINT
CPI 'K'-'@' ; CTL-K to end listing?
JZ PASSINT
CPI 'K' ; Capital-K to end listing?
JZ PASSINT
CPI 'k' ; Small-k to end listing?
JZ PASSINT
CPI 'S'-'@' ; CTL-S to delay listing?
JNZ WELTYPE ; No, loop until EOF
;
WAIT: CALL MSTAT
ORA A ; Has another char been typed?
JZ WAIT ; No, wait
CALL MINPUT ; Yes, check character
CPI 'C'-'@' ; Did user type a CTL-C to end listing?
JZ PASSINT
CPI 'K'-'@' ; CTL-K to end listing?
JZ PASSINT
CPI 'K' ; Capital-K to end listing?
JZ PASSINT
CPI 'k' ; Small-k to end listing?
JNZ WELTYPE ; None of these, loop until EOF
ENDIF ; WELFILE
;
;
; Get the password
;
PASSINT: IF PWRQD
MVI D,3 ; 3 tries at password
;
PASSINP:LXI H,PWMSG ; Password message
CALL PRINTB ; Send this message
LXI H,PASSWD ; Point to password
MVI E,0 ; No missed letters
;
PWMLP: CALL MINPUT ; Get a character
CPI 60H ; Lower case?
JC NOTLC ; No,
ANI 5FH ; Make upper case alpha
;
NOTLC: PUSH PSW ; Save character input
CPI 20H ; Is character a control code?
JNC PWDIS ; Pass if displayable
MVI C,'^' ; Dislay if control map to up arrow
CALL CONOUT
POP PSW
PUSH PSW
ADI 40H
;
PWDIS: MOV C,A
CALL CONOUT ; Output character locally
POP PSW ; Restore 'A' reg.
CPI 'U'-40H ; CTL-U?
JZ PASSINP ; Yes, abort, and retry
CMP M ; Match password?
JZ PWMAT
MVI E,1 ; No, show miss
CPI CR ; CR?
JNZ PWMLP ; No, wait for CR
;
;
; Password did not match
;
PWNMAT: LXI H,WRGMSG ; Wrong password message
CALL PRINTB ; Send this message
DCR D ; More tries?
JNZ PASSINP ; Yes
JMP PREOFF ; No, go hang up
;
;
; Character matched in password
;
PWMAT: INX H ; To next character
CPI CR ; End?
JNZ PWMLP ; No, loop
;
;
; End of password, any missed characters?
;
MOV A,E ; Get flag
ORA A
JNZ PWNMAT ; Not right
;
LXI H,NWPWD ; Get last value
INR M ; And add one
ENDIF ; PWRQD
;
IF COMFILE
MVI C,SETUSR
MVI E,COMUSR ; Switch to .COM file user area
CALL BDOS
MVI C,SELDSK ; In case welcome
MVI E,COMDRV-'A' ; Is on different drive
CALL BDOS ; Than com file
MVI A,' ' ; Fool the system so that the .COM file
STA FCB+1 ; Will see a space at FCB+1 for default
ENDIF ; COMFILE
;
; Either run the COM file or warmboot to cp/m
;
IF ZCPR3 AND COMFILE
CALL DOZ3 ; ZCPR3 re-initialization
ENDIF ; ZCPR3 and COMFILE
;
IF COMFILE
CALL PATCH ; Run under bye if running "E" option
CALL 100H ; Execute com file
ENDIF ; COMFILE
;
JMP 0000H ; Warm boot now for "normal" CP/M use
;......
;
PREOFF:
LXI SP,STACK ; Insure valid stack
CALL IMDONE ; Hangup the phone
CALL UNPATCH
XRA A
STA OPTION ; Reset the local "E" option
;
IF DISKLOG
LXI H,DSCMSG
CALL WRTMSG ; Put disconnect msg into SYS.LOG
ENDIF ; DISKLOG
;
JMP HANGUP ; And prep for next call
;
IF TABBY
;
; Get the time (hour and minute) of the next tabby event
GETNXE:
MVI C,SELDSK
MVI E,TBYDRV-'A'
CALL BDOS
;
MVI C,SETUSR
MVI E,TBYUSER
CALL BDOS
MVI A,TBYUSER*010H+TBYDRV-'A' ;This makes SURE we are on
STA 0004H ; the right drive and user for $$$.sub files
;
LXI D,80H
MVI C,STDMA
CALL BDOS
;
LXI D,EVNTFCB
MVI C,OPEN
CALL BDOS
INR A
JZ TBYEXIT ; No NXTEVENT file found, try to create one
LXI D,EVNTFCB
MVI C,READ
CALL BDOS
;
LXI D,EVNTFCB
MVI C,CLOSE ; CLOSE
CALL BDOS
;
LDA 80H+8 ; ADDRESS OF NEXT EVENT HOUR
CALL BINBCD
STA NXTHR
;
LDA 80H+10 ; ADDRESS OF NEXT EVENT HIMUTE
CALL BINBCD
STA NXTMN
;
LDA 80H+14 ; NEXT EVENT LENGTH
CALL BINBCD
STA NXTLEN
;
LDA 80H+22 ; NEXT EVENT NAME
STA NXTEVN
;
RET
ENDIF ;TABBY
;.....
;
;-----------------------------------------------------------------------
; calculate user's elapsed time
;
; Calculate time on system. Log him off if =>MAXMIN unless WHEEL is
; on, or MXTIME=0. If MXTIME = 255, user not logged in.
;
IF TIMEON OR CLOCK
TCHECK: LDA TCHKFG
INR A
RZ ; If mxtime was 255, user not logged in
PUSH B
PUSH D
PUSH H
ENDIF ; TIMEON OR CLOCK
;
IF TIMEON AND (NOT CLOCK)
LDA TON
JMP TCNCLK
ENDIF ; NOT CLOCK
;
IF TIMEON AND CLOCK
CALL TIME ; Get current time
LDA LHOUR ; (LHOUR)=log-in hour 0-23
CALL TCX60 ; Convert to minutes, results in (HL)
LDA LMIN ; (LMIN)=log-in minutes, 0-59
LXI D,0 ; Clear (DE)
MOV E,A ; (LMIN) to (DE)
DAD D ; (HL)+(DE)=(HL)
PUSH H ; Save log-in minutes on stack
LDA CCHOUR ; (CCHOUR)=current hour, 0-23
LXI H,LHOUR ; Let's see if we crossed midnight
SUB M
JNC TCOK ; No, we're ok
LDA CCHOUR ; Yes, let's add 24
ADI 24
STA CCHOUR ; Now we're ok
;
TCOK: LDA CCHOUR ; (CCHOUR) is now => than (LHOUR)
CALL TCX60 ; Convert it to minutes
LDA CCMIN ; Current minutes, 0-59
LXI D,0 ; Clear (DE)
MOV E,A ; CCMIN to (DE)
DAD D ; (HL) now has current time in minutes
POP D ; (DE) now has log-in time
CALL TCDIF ; Get the difference, (HL)-(DE)=(HL)
MOV A,L ; Only save LSB, 0-255 is plenty
STA TON ; And save it
ENDIF ; TIMEON AND CLOCK
;
IF TIMEON
TCNCLK: LXI H,TONMSD ; (A)=TON, (HL)=address to store ascii
CALL DEC8 ; Convert timeon to ascii
LDA TON
MOV B,A
LDA MXTIME
SUB B ; Calculate time-left
LXI H,TLNMSD
CALL DEC8 ; And save it as ascii
POP H
POP D
POP B
ENDIF ; TIMEON
;
IF TIMEON AND (ZCPR2 OR ZCPR3)
LDA WHEEL
ORA A ; Maybe he typed his password for user
RNZ
ENDIF ; TIMEON AND ZCPR
;
IF TIMEON
LDA MXTIME
ORA A ; Special user?
RZ ; Yes, exit
PUSH B ; Else, check his timeon
MOV B,A ; Move it to 'B'
LDA TON
SUB B ; Subtract max time allowed
POP B
RC ; Still time left
LXI SP,STACK ; Insure valid stack
MVI A,255
STA TCHKFG ; Reset time flag
XRA A
LXI H,TLNMSD
CALL DEC8 ; Make sure time-left =0
LXI H,TIMEUP ; Time is up, inform user
CALL PRINTB
CALL PATCH ; In case LUX was running
ENDIF ; TIMEON
;
IF DISKLOG AND TIMEON
XRA A
STA BDOSFL
LXI H,TLMMSG
CALL WRTMSG ; Put time limit message into log file
ENDIF ; DISKLOG AND TIMEON
;
IF MBBS AND TIMEON
XRA A
STA MXTIME
JMP NORPTC ; Let login do it
ENDIF ; MBBS AND TIMEON
;
IF TIMEON AND (NOT MBBS)
JMP LOGOFF ; Check for exit file
ENDIF ; TIMEON AND NOT MBBS
;.....
;
; TCX60 will multiply (A)x60, results in (HL).
;
IF CLOCK
TCX60: LXI H,0 ; (HL)=0
ORA A
RZ ; If (A)=0, no x60 needed
LXI D,60 ; Multiplier
;
TCX61: DAD D ; X60
DCR A ; Done?
JNZ TCX61 ; No
RET
;.....
;
;
; TCDIF will subtract (DE) from (HL), results in (HL).
; (HL) normally has the larger number
;
TCDIF: MOV A,L ; LSB of (HL)
SUB E ; LSB of (DE)
MOV L,A ; Back to L
MOV A,H ; MSB of (HL)
SBB D ; MSB of (DE) and carry flag
MOV H,A ; (HL) now has difference
RET
ENDIF ; CLOCK
;
;-----------------------------------------------------------------------
; BCD to Binary converter
;
; This routine will convert an 8 bit BCD number (0-99) to binary.
;
; To use:
; LDA BCDNUMBER
; CALL BCDBIN
;
; The routine returns with the binary number in the 'A' register.
;
IF BCD2BIN
BCDBIN: PUSH D
MOV E,A ; Save original byte
ANI 15
MOV D,A ; Save low nibble
MOV A,E
ANI 240 ; Mask LSN
RRC ; X2
MOV E,A
RRC ; X4
RRC ; X8
ADD E ; X10
ADD D ; Low nibble
POP D
RET
;
ENDIF ; BCD2BIN
;.....
;
;
; BINBCD will convert a 0-99 binary number to 0-99 BCD number. Call
; with (A)=binary number 0-99. (A)=0-99 BCD on exit
;
IF BIN2BCD
BINBCD: PUSH D
MVI E,255 ; -1
;
BLP: INR E ; Increment tens counter
SUI 10 ; Subtract 10 each pass
JNC BLP
ADI 10 ; Get back number
MOV D,A
MOV A,E
RLC ; Shift over to MSN
RLC
RLC
RLC
ADD D ; Add in ones position
POP D
RET
ENDIF ; BIN2BCD
;.....
;
;
;-----------------------------------------------------------------------
;
; DEC8 will convert an 8 bit binary number in A to 3 ASCII bytes.
; HL points to the MSB location where the ASCII bytes will be stored.
; Leading zeros are suppressed and spaces are stored in unused bytes.
;
DEC8: PUSH PSW
PUSH H
MVI A,' '
MOV M,A ; Clear destination with spaces
INX H
MOV M,A
INX H
MOV M,A
POP H
POP PSW
PUSH B
PUSH D
MVI E,0 ; Leading zero flag
MVI D,100
;
DEC81: MVI C,'0'-1
;
DEC82: INR C
SUB D ; 100 or 10
JNC DEC82 ; Still +
ADD D ; Now add it back
MOV B,A ; Remainder
MOV A,C ; Get 100/10
CPI '1' ; Zero?
JNC DEC84 ; Yes
MOV A,E ; Check flag
ORA A ; Reset?
MOV A,C ; Restore byte
JZ DEC85 ; Leading zeros are skipped
;
DEC84: MOV M,A ; Store it in buffer pointed at by HL
INX H ; Increment storage location
MVI E,0FFH ; Set zero flag
;
DEC85: MOV A,D
SUI 90 ; 100 to 10
MOV D,A
MOV A,B ; Remainder
JNC DEC81 ; Do it again
ADI '0' ; Make ascii
MOV M,A ; And store it
POP D
POP B
RET
;.....
;
;
;-----------------------------------------------------------------------
;
IF CHGPATH ; To alter path
REMPAT: LXI H,REMPATH ; Source=remote path
LXI D,EXTPATH ; Dest=external path at 0040H
MVI B,LREMP ; Length of remote path
CALL MOVE
RET
;
SYSPAT: LXI H,SYSPATH ; Source=SYSOP's path
LXI D,EXTPATH ; Dest=external path at 0040H
MVI B,LSYSP ; Length of new path
CALL MOVE
RET
ENDIF ; CHGPATH
;.....
;
;
;-----------------------------------------------------------------------
; SCB manipulation for CP/M Plus
;
; Set SCB byte at offset in [B] to value in [A]
;
IF CPM3
SETSCB: LHLD SCBBASE ; Get SCB pointer
MOV L,B ; Set the offset
MOV M,A ; Save the byte
RET
;
;
; Get SCB byte at offset in [B] to [A]
;
GETSCB: LHLD SCBBASE ; Get SCB pointer
MOV L,B ; Set the offset
MOV A,M ; Get the byte
RET
;
;
; Set user number to value in [A]
;
SETUSER:MVI B,0B0H ; B0 = CCP user number
CALL SETSCB ; Set CCP user number
MVI B,0E0H ; E0 = BDOS user number
JMP SETSCB ; Set BDOS user number
;
;
; Set drive to value in [B]
;
SETDRIVE:
MVI B,0AFH ; AF = CCP drive
CALL SETSCB ; Set CCP drive
MVI B,0DAH ; DA = BDOS drive
JMP SETSCB ; Set BDOS drive
ENDIF ; CPM3
;.....
;
; End of SCB manipulation routines
;-----------------------------------------------------------------------
;
IF NOT CPM3
ENDOBJ EQU $
ENDIF ; NOT CPM3
;
; end of main body of program
;-----------------------------------------------------------------------
;
; ------------------------------------------------
; START B5IM COMMANDS (Set B5IM EQU YES to use this)
; ------------------------------------------------
;
IF B5IM AND DOATZ
B5ATZ: DB 'ATZ',CR,0 ; Reset modem
ENDIF ; B5IM AND DOATZ
;
IF B5IM AND NODTR
B5ESC: DB '+++',0 ; Escape sequence for command mode
B5ATH: DB 'ATH',CR,0 ; Hangup phone
ENDIF ; B5IM AND NODTR
;
IF B5IM AND OFFHK
B5ATH1: DB 'ATH1' ; Take phone off-hook
ENDIF ; B5IM AND OFFHK
;
IF B5IM AND OFFHK AND (NOT ANCHOR)
DB 'M0' ; Make sure speaker is off
ENDIF ; OFFHK AND NOT ANCHOR
;
IF B5IM AND OFFHK
DB CR,0 ; End the command line
ENDIF ; B5IM AND OFFHK
;
IF B5IM
B5ATA: DB 'ATA',CR,0 ; Answer the phone
ADDSTR: DW 0 ; Address of command string
VCMSG: DB CR,LF,'Voice calls: '
VCMSN: DB ' ',0
VCNUM: DB 0 ; Counter for voice calls
ENDIF ; B5IM
;
IF B5IM AND PRGRSS
RCSHOW: DB '_',0 ; Will be stored by PRGRSS
NOEMSG: DB CR,LF,'Echo error',CR,LF,0
CMDERR: DB 'Modem error',CR,LF,0
ENDIF ; B5IM AND PRGRSS
;
IF B5IM
B5INIT: DB 'AT' ; Attention
ENDIF ; B5IM
;
IF B5IM AND ECHO
DB 'E1' ; Echo back characters sent to modem
ENDIF ; B5IM AND ECHO
;
IF B5IM AND (NOT ECHO)
DB 'E0' ; Don't do echo verification
ENDIF ; B5IM AND NOT ECHO
;
IF B5IM
DB 'Q0' ; Send result codes
DB 'V0' ; Terse mode
ENDIF ; B5IM
;
IF B5IM AND (NOT NOATA)
DB 'S0=0' ; No auto-answer (we will use 'ATA')
ENDIF ; B5IM AND NOT NOATA
;
IF B5IM AND NOATA
DB 'S0=1' ; Will answer on first ring
ENDIF ; B5IM AND NOATA
;
IF B5IM AND SHORTB
DB CR,0
B5INT1: DB 'AT'
ENDIF ; B5IM AND SHORTB
;
IF B5IM AND (NOT ANCHOR)
DB 'M0' ; Speaker off
DB 'S10=25' ; 2 1/2 sec wait after carrier loss to
; Hang up
ENDIF ; B5IM AND NOT ANCHOR
;
IF B5IM AND (NOT HS300) AND (NOT ANCHOR)
DB 'X1' ; Extended response codes beyond '4'
ENDIF ; B5IM AND NOT HS300 AND NOT ANCHOR
;
IF B5IM
DB 'H0' ; Put modem on-hook
DB CR,0 ; CR finishes command string
ENDIF ; B5IM
;
IF B5IM AND (NOT OFFHK)
B5USR: DB 'ATS0=0',CR,0 ; This helps the Password and S-100
ENDIF ; B5IM
;.....
;
; end of B5IM command strings
;-----------------------------------------------------------------------
; messages
;
IF PRGRSS AND (NOT B5IM)
MSG30: DB '300 baud test',CR,LF,0
MSG12: DB '1200 baud test',CR,LF,0
MSG24: DB '2400 baud test',CR,LF,0
ENDIF ; PRGRSS AND (NOT B5IM)
;
;
; Program version number message
;
VMSG: DB CR,LF,'BYE',MAIN+'0'
DB VERS/10+'0',VERS MOD 10+'0',' - '
DB MONTH/10+'0',MONTH MOD 10+'0','/'
DB DAY/10+'0',DAY MOD 10+'0','/'
DB YEAR/10+'0',YEAR MOD 10+'0',CR,LF,LF,0
;
CLRSEQ: DB CLRCH1,CLRCH2,CLRCH3,CLRCH4,CLRCH5,CLRCH6,0
;
IF RVIDEO
RVIDON: DB RVON1,RVON2,RVON3,RVON4,0
RVIDOFF:DB RVOFF1,RVOFF2,RVOFF3,RVOFF4,0
ENDIF ; RVIDEO
;
BELMSG: DB 7,7,0 ; Alert sysop that system is available
CDOFF: DB 0
OPTION: DB 0
;
IF RSPEED
OFFMSG: DB CR,LF,'Sorry! 1200 or 2400 baud only allowed 7PM-11PM'
DB CR,LF,CR,LF,' Call back before/after 7-11PM Pacific'
DB CR,LF,0
ENDIF ; RSPEED
;
IF TIMEON
TIMEUP: DB 7,7,CR,LF,CR,LF
DB ' Your time is up - wait 24 hours to call back',CR,LF,0
TONMSG: DB CR,LF,'Minutes on system: '
TONMSD: DB '0 ',CR,LF,0
TLNMSG: DB CR,LF,'Minutes left: '
TLNMSD: DB '0 ',CR,LF,0
ENDIF ; TIMEON
;
RTCBUF:
;
; Real-Time clock buffer. Store BCD values into this area if TIMEON
; is YES and your clock is read as BCD values for time and date. Use
; BCDBIN to convert HH and MM to binary and store those values in
; CCHOUR and CCMIN.
;
; (NOTE: 99:99:99 INDICATES CLOCK IS NOT RUNNING OR NOT AVAILABLE)
;
;
DB 99H,99H,99H ; HH:MM:SS (BCD 24hr time)
; 00:00:00-23:59:59
DB 19H,85H,02H,18H ; YYYY/MM/DD (BCD ISO date)
;
TON: DB 0,0 ; (Total time on system-binary integer)
CCHOUR: DB 0 ; Current clock hour in binary
CCMIN: DB 0 ; Current clock minute in binary
LHOUR: DB 0 ; Login hour in binary
LMIN: DB 0 ; Login minutes in binary
TCHKFG: DB 0 ; Tcheck flag, 0 = OK, 255 = not OK to
; Check
;
CRMSG: DB CR,LF,CR,LF,0
;
TERMSG: DB CR,LF,'BYE5', VERS/10+'0',VERS MOD 10+'0',' (c)'
;
IF NOT SKTERM
DB ' - Hit any key to continue: '
ENDIF ; NOT SKTERM
;
DB CR,LF,CR,LF,0 ; End of message
;
FKFLAG: DB 0
PTFLAG: DB 0
;
IF PRNTGB
GBMSG: DB CR,LF,' Goodbye, call again...',CR,LF,' '
DB CR,LF,0
ENDIF ; PRNTGB
;
RS1MSG: IF COMFILE
DB CR,LF,'<E>xecute .COM file,'
ENDIF ; COMFILE
DB CR,LF,'<R>esume BYE,'
DB CR,LF,'<J>ump to CP/M with BYE5 attached,'
DB CR,LF,'<RET> for normal unpatched CP/M: ',0
;
RS2MSG: DB ' Resuming...',CR,LF,0
ATMSG: DB CR,LF,'Modem calls: '
ATMSN: DB ' ',0
CWCAR: DB 0 ; Counter for carrier detected calls
;
;
; Access password (ends in carriage return) - keep password here
;
IF PWRQD
PASSWD: DB 'DDT' ; The password itself
DB CR ; End of password, CR-only to erase it
;
;
; (Allow room for larger password to be entered, up to 10 characters)
;
DB 0,0,0,0,0,0,0
;
PWMSG: DB CR,LF,'Enter Password: ',0
WRGMSG: DB 'Incorrect password',CR,LF,0
NWMSG: DB CR,LF,'Passwords: '
NWMSD: DB ' ',0
NWPWD: DB 0 ; Counter for correct password callers
ENDIF ; PWRQD
;
IF CHEKDU
IDMSG: DB '> [Invalid drive]',0
IUMSG: DB '> [Invalid user#]',0
ENDIF ; CHEKDU
;
CLMSG: DB CR,LF,LF,'[Carrier lost]',CR,LF,0
ITOMSG: DB CR,LF,LF,'[Input timed out]',7,CR,LF,0
LCDMSG: DB CR,LF,LF,'[Last call]',CR,LF,0
ULTMSG: DB CR,LF,'[Unlimited Time]',CR,LF,0
SCRMON: DB CR,LF,'[Remote on]',CR,LF,0
SCRMOFF:DB CR,LF,'[Remote off]',CR,LF,0
BELMON: DB CR,LF,'[Bell on]',CR,LF,LF,0
BELMOFF:DB CR,LF,'[Bell off]',CR,LF,LF,0
MFSMSG: DB CR,LF,'Message from Sysop: ',CR,LF,0
SGDMSG: DB CR,LF,'Going down in ',DOWNMIN+'0'
DB ' min.',CR,LF,0
LFMSG: DB CR,LF,0
LCDFLG: DB 0
;
IF PRNTWB
WBMSG: DB CR,LF,'Booting CP/M...',CR,LF
DB 0
ENDIF ; PRNTWB
;
IF CPM3
SCBPB: DB 03AH,0 ; Parameter block for extracting SCB
; Start address
ENDIF ; CPM3
;
IF COMFILE OR EXFILE OR TABBY
PTSMSG: DB '++ TPA too small ++',0
CNFMSG: DB '.COM ++ Not found-abort ++',CR,LF,0
ENTMSG: DB 'Entry ',0 ; Filled by loader
CFLMSG: DB '.COM loaded',CR,LF,LF,0
ENDIF ; COMFILE OR EXFILE OR TABBY
;
IF EXFILE
EXTMSG: DB 'Exit ',0 ; Filled by loader
ENDIF ; EXFILE
IF TABBY
NXTHR: DB 0
NXTMN: DB 0
NXTLEN: DB 0
NNHMSG: DB 'Processing mail only now -- please call back later.',CR,0
ENDIF ; TABBY
;
IF CLKDSP OR TABBY
TIMESG:
ENDIF ; CLKDSP OR TABBY
;
IF CLKDSP
DB '1988/12/31 08:01:01 '
ENDIF ; CLKDSP
;
IF TABBY
DB ' Next TABBY event ('
NXTEVN: DB 0
DB ') at '
EVENHR: DB ' :'
EVENMN: DB ' '
ENDIF ; TABBY
;
IF TABBY OR CLKDSP
DB CR,0
ENDIF ; TABBY OR CLKDSP
;
IF TABBY
EVNTFCB:DB 0,'NXTEVENT ' ; Put name of your message handler here
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; TABBY
;
IF MSGFIL
MSGFCB: DB 0,'MFMSG COM' ; Put name of your message handler here
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
MSGMSG: DB 'MSGNAME ',0 ; Filled by loader
ENDIF ; MSGFIL
;
IF WELFILE
WELFILN:DB 0,'WELCOME ???' ; WELCOME file name, must be 11 chars.
DB 0 ; WELCOME or WELCOME.TXT will work
ENDIF ; WELFILE
;
CM2FCB: IF MBBS
DB 0,'MBBS COM' ; For mbbs4n
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; MBBS
;
IF COMFILE AND RBBS
COMFCB: DB 0,'RBBS COM' ; COM file name, must be 11 characters
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; COMFILE AND RBBS
;
IF COMFILE AND OXGATE
COMFCB: DB 0,'OXENTR COM' ; OxGate entry module
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; COMFILE AND OXGATE
;
IF COMFILE AND METAL
COMFCB: DB 0,'MENTR COM' ; Metal entry file
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; COMFILE AND METAL
;
IF COMFILE AND MBBS
COMFCB: DB 0,'LOGIN COM' ; Mbbs entry file
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; COMFILE AND MBBS
;
IF COMFILE AND PBBS
COMFCB: DB 0,'PBBS COM' ; PBBS entry file
DB 0,0,0,0,0,0,0 ; 21 more for fcb
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; COMFILE AND PBBS
;
IF COMFILE AND DRBBS
COMFCB: DB 0,'DRBBS COM' ; DRBBS entry file
DB 0,0,0,0,0,0,0 ; 21 more for fcb
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; COMFILE AND DRBBS
;
IF COMFILE AND QBBS
COMFCB: DB 0,'QENTER COM' ; QBBS entry module
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; COMFILE AND QBBS
;
EXITFCB: IF EXFILE AND QBBS
DB 0,'QEXIT COM' ; Exit filename, must be 11 characters
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; EXFILE AND QBBS
;
IF EXFILE AND OXGATE
DB 0,'OXEXIT COM' ; Exit filename, must be 11 characters
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; EXFILE AND OXGATE
;
IF EXFILE AND METAL
DB 0,'MEXIT COM' ; Exit filename, must be 11 characters
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; EXFILE AND METAL
;
IF EXFILE AND PBBS
DB 0,'PBYE COM' ; Exit filename, must be 11 characters
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
ENDIF ; EXFILE AND PBBS
;
IF TABBY
TBYXFCB:DB 0,'DISPATCHCOM' ; Exit filename, must be 11 characters
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
DSPMSG: DB 'DISPATCH',0
;
TBYFCB: DB 0,'RECVMAILCOM' ; Exit filename, must be 11 characters
DB 0,0,0,0,0,0,0 ; 21 for rest of FCB
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
RMAILNM:DB 'RECVMAIL',0
ENDIF ; TABBY
;
LCNAME: IF NO25TH OR MBBS
DB 0,'LASTCALR???' ; LASTCALR OR LASTCALR.DAT will be used
DB 0
ENDIF ; NO25TH OR MBBS
;
LCDATA: IF NO25TH OR MBBS
DB ' ',0
DS NO25BF-2 ; Size of buffer
LCFILL: DB ' L/C data N/A',0
LCHEAD: DB CR,0 ; Put your customized header here,
; Terminate with a ,0
ENDIF
;
IF (NO25TH OR MBBS) AND READLC
LCMSG1: DB 'No L/C file',CR,LF,0
ENDIF ; NO25TH OR MBBS
;
IF MBBS
MBBS1: DB CR,LF,'Loading for COMMENT before exiting...',CR,LF,LF,0
MBBS2: DB CR,LF,'[ Updating ]',CR,LF,0
ENDIF ; MBBS
;
;
IF DISKLOG
DSKLOG: DB 0 ; Disk log open status
OPNMSG: DB CR,LF,'[Log on]',CR,LF,0 ; Function key message
CLSMSG: DB CR,LF,'[Log off]',CR,LF,0 ; Function key message
DSCMSG: DB '**DISCONNECT**',0 ; Log disconnect msg
CONMSG: DB '**CONNECT ' ; Connect message
CONMS1: DB ' on '
CDAY: DS 8
DB '**',0
ENDIF ; DISKLOG
;
IF DISKLOG AND TIMEON
TLMMSG: DB '**TIME LIMIT**',0 ; Time limit message
ENDIF ; DISKLOG AND TIMEON
;
IF TABBY ; Print this message for TABBY
TBYMSG: DB 'Wait a few seconds or hit <ESCAPE>',cr,0
ENDIF
;
IF DISKLOG
CARMSG: DB '**CARRIER LOST**',0 ; Carrier lost msg
TMOMSG: DB '**INPUT TIMEOUT**',0 ; Timout msg
DRPMSG: DB '**DROPPED**',0 ; Twit key message
VOCMSG: DB '**VOICE CALL**',0 ; Voice call msg
LOGFCB: DB LOGDRV-40H,'SYS LOG' ; Log file fcb
DS 24
WOFFSET:DB 0 ; Current write offset for log
OLDDMA: DW 80H ; Current DMA address
BDOSFL: DB 0 ; BDOS call in progress flag
TIMSFL: DB 0 ; Time stamp flag
LOGTOG: DB 0 ; Log open toggle flag
OLDLUS: DS 4 ; Old environment save area
RECORD: DS 128 ; Log file buffer
HLSAVE: DS 2 ; Temp HL save
DS 40 ; Stack area for log routines
NEWSTK: DS 0
ENDIF ; DISKLOG
;.....
;
;
;-----------------------------------------------------------------------
; ZCPR external paths
;
; ZCPR's external paths available. (ZCPR will always do the current
; drive/current user area)
;
; Command path available for SYSOP
;
IF CHGPATH
SYSPATH:DB 1,0 ; Then do A0:
DB 1,15 ; Then do A15:
DB 0 ; End of path
;
LSYSP EQU $-SYSPATH
;
;
; Command path available for remote user
;
REMPATH:DB 1,0 ; Then do A0: (don't do A15:)
DB 0 ; End of path
LREMP EQU $-REMPATH
ENDIF ; CHGPATH
;.....
;
; end of ZCPR external paths
;-----------------------------------------------------------------------
;
; These areas are not initialized
;
IF NOT CPM3
PEND EQU $ ; The following area is not initialized
ENDIF ; NOT CPM3
;
IF COMFILE OR EXFILE OR TABBY
CURRFCB:DS 2
ENDIF ; COMFILE OR EXFILE
;
TOCNTM: DS 1
TOCNT: DS 2
MSFLAG: DS 1
;
;
; Save the CP/M jump table here
;
VCOLDBT:DS 3
VWARMBT:DS 3
VCONSTAT: DS 3
VCONIN: DS 3
VCONOUT:DS 3
VLISTOUT: DS 3
VPUNCH: DS 3
VREADER:DS 3
;
;
; System addresses initialized at program startup
;
IF CPM3
SCBBASE:DW 0 ; Base address of the CP/M Plus SCB
MEMBASE:DB 0 ; Base page of common memory
BDOSBASE: DB 0 ; Base page of BDOS
ENDIF ; CPM3
;.....
;
;
;----------------------------------------------------------------
;
; ASCII Equates
;
CR EQU 0DH ; ASCII carriage return
LF EQU 0AH ; ASCII line feed
;
LXID EQU 11H ; Define byte of LIX D,nnnn to fake loader
LXIH EQU 21H ; Define byte of LXI H,nnnn to fake loader
IOBYTE EQU 0003H ; Location of CP/M IOBYTE
FCB EQU 005CH
FCBRNO EQU FCB+32
;
;
; CP/M Plus system variable offsets
;
IF CPM3
SCBDAT EQU 00F4H ; Offset of date into SCB
SCBTIM EQU 00F6H ; Offset of time into SCB
SCBCOM EQU 00FAH ; Offset of common memory base page in SCB
SCBBDOS EQU 0099H ; Offset of base page of BDOS in SCB
ENDIF ; CPM3
;
;
; BDOS equates
;
IF CPM3
BDOS EQU NEXT
ENDIF ; CPM3
;
IF NOT CPM3
BDOS EQU 0005H
ENDIF ; NOT CPM3
;
CI EQU 1
WRCON EQU 2
DRECTIO EQU 6
PRINTF EQU 9
CSTS EQU 11
SELDSK EQU 14
OPEN EQU 15
CLOSE EQU 16
SEARCH EQU 17
READ EQU 20
STDMA EQU 26
SETUSR EQU 32
CHAINP EQU 47
GTSCB EQU 49
DEFPAS EQU 106 ; Set default password BDOS function
;
DS 60
STACK EQU $ ; Local stack
;
IF NOT CPM3
OBJEND EQU $
ENDIF ; NOT CPM3
;.....
;
;
END