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
/
BYE510.LBR
/
BYE510.AQM
/
BYE510.ASM
Wrap
Assembly Source File
|
2000-06-30
|
143KB
|
5,757 lines
; BYE510 - REMOTE CONSOLE PROGRAM FOR CP/M AND MODEM - 08/01/86
;
; 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.
;
; = = = = = = = =
;
; 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 10
MONTH EQU 08
DAY EQU 01
YEAR EQU 86
;
;
; 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+27 ; 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.
;
;-----------------------------------------------------------------------
; 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 NO ; 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 NO ; 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 14 ; 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
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
EXDRV EQU 'A' ; Drive to look for exit .COM file on
EXUSR EQU 14 ; 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 NO ; 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 NO ; 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
LCDRV EQU 'A' ; Drive to find LASTCALR or LASTCALR.DAT
LCUSR EQU 14 ; User # of LASTCALR or LASTCALR.DAT file
;
SKTERM EQU NO ; 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
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 YES ; Yes, for helpful progress reports on
; CRT. Leave this YES until every-
; Thing is working
PRNTGB EQU YES ; 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 'G' ; Bytes. Set unused bytes to nulls (0).
RVON3 EQU '4' ; 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 'G' ; 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 2 ; 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 NO ; 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 NO ; 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
IOVAL EQU 0 ; 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 NO ; 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 NO ; 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 NO ; Yes, your clock routine calls BCDBIN
BIN2BCD EQU NO ; Yes, your clock routine calls BINBCD
TIMEON EQU NO ; 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.
;
; 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, restricting primetime to a min.
; 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 NO ; 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 9 ; Highest user area
SYSDRV EQU 'O'-'@' ; 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 pointera
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|
; |3 byt|1 byt|1 byt|2 byt|1 byt|2 byte|
;-----------------------------------------------------------------------
;
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
;
;
; 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
;
;-----------------------------------------------------------------------
;
; ++++ 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
TIME: RET ; Install your clock code here
ENDIF ; CLOCK OR RSPEED
;
; 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 ; 400 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)
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
JMP LOGOFF ; Run the exit file
ENDIF ; EXFILE
;
IF PRNTGB AND (NOT EXFILE)
LXI H,GBMSG ; Goodbye message
CALL PRINTB ; Print this message
ENDIF ; PRNTGB AND NOT EXFILE
;
IF NOT EXFILE
CALL IMDONE ; Hang up the phone before doing this
CALL UNPATCH ; Undo BIOS patches
ENDIF ; NOT EXFILE
;
;.....
;
IF DISKLOG AND (NOT EXFILE)
LXI H,DSCMSG ; Disconnect message
CALL WRTMSG ; Put it into log file
ENDIF ; DISKLOG AND NOT EXFILE
;
;
; 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 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: 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 RINGWT
ENDIF ; B5IM
;
IF NOT B5IM
CALL MDCARCK ; Carrier?
JZ RINGWT ; 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
CALL MDINP ; Clear garbage characters
CALL MDINP
;
;
; 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
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
LDA WRTLOC ; Get write in progress flag
ORA A
RNZ ; Busy, wait until done
ENDIF ; RBBS OR MBBS OR PBBS OR QBBS
;
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 ; EXITFIL was loaded ok, so run it
ENDIF ; EXFILE
;
IF EXFILE AND (NOT BYHANG)
CALL MDCARCK ; Still have carrier after exfile ran?
JZ PREOFF ; No, skip this
ENDIF ; EXFILE AND NOT BYHANG
;
IF CLOCK AND TIMEON AND EXFILE AND (NOT BYHANG)
CALL RMTOS ; Print time data
ENDIF ; CLOCK.....
;
IF PRNTGB AND EXFILE AND (NOT BYHANG)
LXI H,GBMSG
CALL PRINTB ; Pring goodbye
ENDIF ; PRNTGB...
;
JMP PREOFF ; Prepare for next caller
;.....
;
;
;-----------------------------------------------------------------------
;
; 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
;
;
; 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
;
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
ENDIF ; EXFILE
;
;
; Now load the file
;
IF COMFILE OR EXFILE
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
;.....
;
;
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) 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 AND NOT PBBS
;
IF EXFILE AND (NOT MBBS) AND (NOT 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
ORA A ; Got console input?
JNZ CONIN ; Yep, get the console character
CALL MSTAT ; Nope, check for modem input
ORA A ; Got modem input?
JZ MINP2 ; Nope, loop again
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
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
PUSH PSW ; Yep, save return status
XRA A ; Clear no-activity flag
STA MSFLAG
POP PSW ; Restore return status
RET ; And return
;
MSTAT1: 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: MVI A,'G'-'@' ; Beep the user
CALL MDOUTP
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
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
CALL MDINP ; Clear garbage from modem input
;
IF NOT SKTERM
CALL MINPUT ; Accept any character, then proceed
ENDIF ; NOT SKTERM
;
;
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
;.....
;
;-----------------------------------------------------------------------
; 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 ' - any key to continue: '
ENDIF ; NOT SKTERM
;
DB 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
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
;
IF EXFILE
EXTMSG: DB 'Exit ',0 ; Filled by loader
ENDIF ; EXFILE
;
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 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
;
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 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
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
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 40
STACK EQU $ ; Local stack
;
IF NOT CPM3
OBJEND EQU $
ENDIF ; NOT CPM3
;.....
;
;
END