TITLE 'BYE Vers 7.2K of April 6, 1983' ; VER EQU 72 ;Current version number REV EQU 'K' ;Current sub revsion DAY EQU 06 ;Day of the month in range 1 to 31 MONTH EQU 04 ;Month of the year in range 1 to 12 YEARS EQU 83 ;Year in range 00 to 99 ; ; BYE V7.2 ; REMOTE CONSOLE PROGRAM FOR CP/M AND MODEM ; ;This program allows modem callers to use your CP/M system ;just as if they were seated at the system console. Special ;assembly-time options allow limiting the caller's access by ;password and/or access to only a message-service program. ; ;Based on an original program written by Dave Jaffe, January 1979 ;Rewritten for PMMI modem by Ward Christensen, February 1979. ;Be sure to set the equates for the modem ;you are using. ; ;Thanks to Bill Precht for the "label + offset" idea allowing ;this program to relocate itself without using DDT to initially ;set it up. ; ;Adapted for Telecom Australia Auto answer modem ;operation with 2651 based UART interface. April, 1982 ; ;Bill Bolton, ;Software Tools, ;P.O. Box 80, ;Newport Beach, ;NSW, 2106, ;Australia. ; ;Modifications/fixes: (in reverse order to minimize reading time) ; ;06/Oct/83 Added optional code to limit number of attempts at answering ; questions to stop turkeys from monopolising the system all ; day by setting up programs that just send occasional CRs, ; (yes folks they DO exist). Tries for the "nulls" response ; can be set to a different (probably higher) number from that ; for the remaining questions. Ver 7.2K ; ;07/Oct/82 Fixed BCD math bug in BOPLOG, replaced INR A with ; ADI 1 as carry flag was upsetting DAA when number passed ; 100 BCD. Ver 7.2J ; ;02/Sep/82 Rearranged auto logoff warning code. Made the command ; line passed to CCP "silent" to remote user so they can't ; tell what the exit file is called. No new Version number. ; ; ;27/Aug/82 Added conditional code to perform a "real" warm boot after ; inactivity timeout and then pass out a fixed command line ; to load a .COM file. Performing a warm boot should always be ; safe if there has been no activity for several minutes. I ; experimented with using LODCOM to load a file but the most ; likely case for a timeout is when waiting for a respone to the ; CP/M ">" prompt. This means that the call to MINPUT has ; already come through the BDOS so any attempt at a BDOS call ; results in reentering the BDOS and as we all know its not ; renterent. A warm boot avoids this problem and cancels all ; bets. I use this feature to execute a program called TIMEOUT ; ( a modified EXITRBBS) which records the auto logoff against ; the users name in the CALLERS file and then renters BYE for a ; normal logout. This leaves a carrier loss as the only ; "uncontrolled" exit from the RCPM system. Also added ; conditional code to give the user a warning of impending ; auto logoff a predetermined time before it happens. Ver 7.2I ; ;26/Aug/82 Added code to count inactivity timeouts, added WELFILE equate ; to disable "WELCOME" file display code if not needed. ; Removed KDELAY routine and adjusted MINUTES equate so that ; DELAY could do it all. Ver 7.2H ; ;08/Aug/82 Added code to reset mode of 2651 UART before each new call. ; This will force a reseting of the baud rate etc., in case ; it got glitched. Also added date and version equates for ; signon message to make maintenance easier. Ver 7.2G ; ;25/Jun/82 Added conditional code to trap RST 7 and jump to a ; Warm Boot. Ver 7.2F ; ;18/Jun/82 Added code to clear tx register of the UART after ; each carrier loss. With CCITT direct connect modems ; CTS goes inactive simultaneously with Carrier detect. ; On the 2651 UART, CTS inactive clamps the transmitter ; even if its in the middle of a character. ; If carrier was permanently lost in the middle of a ; character, this would sometimes clamp the 2651 ; transmitter in a "space" condition. The next caller would ; get "ANSWER" carrier offset to the "space" and some modems ; don't carrier detect on that, therefore CD and CTS never went ; active and never unclamped the transmitter (round and round ; in ever decreasing circles until it....). Ver 7.2E ; ;16/Jun/82 Added conditional code for "flip" to answer mode after ; upper case question. Ver 7.2D ; ;11/Jun/82 Added code to protect current state of frequency mode ; bit in command byte of UART during error reset and also ; added a few more UART equates. Ver 7.2C ; ;25/May/82 Added ring detect to carrier timeout loop enable full ; carrier detect period after answering a new call and to ; prevent hanging up on new call as soon as it is answered ; if it arrived at the end of a timeout period. Added ; CTIME equate for carrier timeout period. Ver 7.2B ; ;24/May/82 Added correct error reset code for 2651 to overcome ; the system sending data but refusing to accept data from ; modem. Many comments tabbed over to constant column ; position. Carrier dropout counter added to detect ; Telecom "open line" beep which occurs if remote user ; hangs up or line drops out. Telecom modems detect this ; as intermitant carrier and otherwise BYE will never ; time out. Ver 7.2A ; ; 6/Apr/82 Deleted DC Hayes and PMMI routines and replaced ; with general purpose UART interface to control Telecom ; auto answer modem. Deleted CPM2 switch, now permanently ; set for CPM2. UART may be banked type. Deleted ringback ; code. ; ;11/Oct/81 Print password on local console with DUAL$IO. Allow ; return from PRNLOG with USRLOG. Make instead ; of in USRLOG reports. Print out BYE version ; number for easy identification. Position PRNLOG after ; cold boot routine, and change cold boot routine to ; jump to MBOOT, thereby defining path to PRNLOG for ; all BYE programs and allowing one trivial program ; that can be run to get the BYE log. Make counters ; 16 bits for greater range. By Steve Bogolub ; ;1/Oct/81 Added CALL CHECK to MSTAT routine to eliminate ; possibility of system crash when carrier lost while ; performing repeated console status checks without ; any console output. This problem occurs during the ; password input of USERPW.ASM, and potentially any other ; program that does repeated direct console input, such ; as MBASIC, etc. ; By Ron Fowler and Dave Hardy ; ;14/May/81 Added CCS disk support (to turn off disks when idle) ; Added support for Godbout SS1 Real time clock. ; Added Phone to Lister, Punch & Reader patch. (AAJ) ; ;20/Mar/81 Fixed MOUTPUT so parity bit is stripped before outputting ; character to modem. Corrected 3/18/81 null fix. Added ; additional description to heading of this file. (KBP) ; ;18/Mar/81 Add first-ring debounce routine, change PMMI HANGUP ; to do break for faster disconnect, fix error in P3TODTR ; equate for PMMI, added end-of-program error message to ; mark ending address (see note at label DEST). By KBP. ; Fix bug that prevented nulls at end of line if DUAL$IO ; was true. By Hank Szyszka. ; ;23/Feb/81 Conditional assembly added for Intertec SuperBrain ; with Racal-Vadic 3451 modem. Corrected lack of RET in ; CONIN. In MOUTPUT, replaced CZ CHECK with JNZ SILENT, ; CALL CHECK; this eliminates chance of looping in MOUTPUT ; if modem doesn't empty USART after carrier lost. ; Also had to write a routine to patch BIOS so that after ; the warm boot disk read this program repatches the BIOS. ; Apparently the SuperBrain warm boot overwrites a portion ; of the BIOS. By P.L. Kelley ; ;17/Feb/81 Added check for extraneous control characters in ; hardcopy log. (Formfeed seems to be a common "hit"). ; Changed local startup test to directly test for carrier ; instead of calling CARCK, to avoid 15 second delay. ; ; ;15/Feb/81 Removed dependance on DC Hayes hardware timer so that ; DCHAYES conditional assembly is compatible with both ; old-style 80-103A and new-style MM100 boards. ; Rearranged patch list to "most recent first" order. ; Added message for invalid-drive test. ; Added ANI 7Fh to upper case conversion test so that ; it's not fooled by bit 7 being set. ; Added WELUSR equate for user # containing WELCOME file. ; Removed PTRPORT equate and changed hardcopy logic to ; work through the BIOS printer driver. ; ;22/Jan/81 CHANGED CARRIER DETECT ROUTINE FOR DC HAYES TO WAIT FOR ; 15 SECONDS AFTER LOSS OF CARRIER TO RETURN. ; ;17/Jan/81 CHANGED TIMING LOOPS TO USE DC HAYES HARDWARE TIMER ; IF PRESENT. ; ;16/Jan/81 ADDED EQUATES AND CODE FOR THE DC-HAYES ; MICROMODEM 100. ; ;23/Sep/80 Fixed bugs that prevented "bye /a" and "bye /c" from ; working properly. Also repaired several errors in ; conditional assembly nesting. -->Ron Fowler ; ;20/Sep/80 Modified status checking during ring-wait routine to ; use cp/m BDOS call, as suggested by Keith Petersen. ; This should make the program more portable. Also ; added Bruce Ratoff's update to DCHBYE program (5.5), ; that allows the use of bye from non-zero user areas. ; By Ron Fowler ; ;19/Sep/80 Modified COM file load routine to prevent BDOS ; overwrite if the COM file won't fit in the TPA ; By Ron Fowler ; ;19/Sep/80 Added new '/' option C, which has the same affect as ; /A, except that /C loads the com file after answering ; the phone, while /A boots cp/m. ; By Ron Fowler ; ;19/Sep/80 Added conditional assembly to give the operator a ; 'twit' logout key. Added conditionals for 'message ; from operator' and 'system down in 5 minutes' keys. ; Added front-panel selection of hard-copy log, remote ; 'black-out', and password option. Also, if cpm/2 is ; used, a message is printed when an unsupported user ; area is entered. ; By Ron Fowler and Dave Hardy ; ;19/Sep/80 Modified to prevent re-load of the com file when ; a voice call comes in. Reset the DMA address back ; to 80h after the com file is loaded. ; By Ron Fowler ; ;16/Sep/80 Added conditional assembly to allow automatic ; loading of a com file instead of cp/m boot. Also ; added decimal usrlog counters as conditional as- ; sembly. ; By Ron Fowler ; ;15/Sep/80 Added conditional assembly for automatic timed ; log-out, drive and user number masking, lower ; case query at login, and cp/m 2.x. Thanks to ; Bruce Ratoff for the routines (lifted from his ; 'DCHBYE54.ASM') used to implement these functions ; NOTE: in order to implement the timed log-out, it ; was necessary to do timing in software loops. ; Therefore, a new equate, FASTCLK, has been added ; to allow for 4mhz clock speeds. Also added Bruce ; Ratoff's overrun/framing error checking when read- ; ing the modem port. ; By Ron Fowler ; ;16/Jul/80 Added "/R" command option to allow USRLOG ; counters to be reset upon entry. ; By Dave Hardy ; ;11/Jul/80 Added conditional assembly for password and ; user log routines, and routines to print USRLOG ; information on console after program exit. ; By Dave Hardy ; ;10/Jul/80 Added code to allow auto-answer after first ; or second ring for more reliable auto-answer ; when using "ringback" option. ; By Dave Hardy ; ;29/Jun/80 Added USRLOG routines to keep track of number ; of callers, and display on front panel ; of IMSAI (i.e. output number to port FFH). ; By Dave Hardy ; ;11/Jun/80 Added 710 Baud rate selection option at sign-on. ; By Dave Hardy and Bruce Levison. ; ;11/Jun/80 Added routines to allow conditional assembly for ; Morrow's Discus 2D board (all Rev's) with memory ; mapped I/O. ; By Dave Hardy ; ;24/Jan/80 Added routines to preserve registers when calling ; the user's CBIOS. Added conditional assembly for ; callback feature. Increased stack space to 60. ; By Keith Petersen. ; ;24/Sep/79 Added routines to allow automatic multiple baud ; rate selection, exit to CP/M from local console, ; echo nr. of nulls selected. By Keith Petersen, ; with thanks to Bob Mathias for suggestions. ; ;6/Jul/79 Added routine to allow "callback" operation so modem ; does not answer normal voice calls. By Robbin Hough ; and Keith Petersen, W8SDZ. ; ; ;------------------------------------------------ ; SYSTEM EQUATES FALSE EQU 0 TRUE EQU NOT FALSE BDOS EQU 5 CR EQU 0DH LF EQU 0AH BEL EQU 07H ESC EQU 01BH MINUTES EQU 10*60 ;CONSTANT FOR 1 MIN TIM DLY ; ;CHANGE THE FOLLOWING EQUATE TO AN AREA IN YOUR ;HI MEMORY WHERE THIS PROGRAM MAY PATCH ITSELF IN. ;APPROX MEMORY REQUIREMENTS: UP TO xxxx BYTES. ; DEST EQU 0F400H ;RUNNING LOCATION OF CODE ; ;YOU WILL LIKELY ALSO WANT TO CHANGE THE PASSWORD, ;LOCATED BELOW AT LABEL "PASSWD", AND THE MESSAGES ;PRINTED AT LABEL "WELCOME" AND JUST ABOVE LABEL ;"HANGUP" ; ;------------------------------------------------ ; ;THIS PROGRAM RUNS UP IN HIGH RAM. IT GETS THERE ;BY BEING MOVED THERE WHEN 'BYE' IS TYPED. ; ;THE PROGRAM IN HI RAM DOES THE FOLLOWING: ; ; 1. HANGS UP THE PHONE ; 2. AWAITS RING DETECT, ALLOWS EXIT ; TO CP/M IF LOCAL KBD TYPES CTL-C ; 3. OUTPUTS CARRIER ; 4. AWAITS INCOMING CARRIER ; GOING TO STEP 1 IF NONE ; FOUND IN 25 SECONDS ; 5. ASKS NUMBER OF NULLS (0-9) ; 6. TYPES THE FILE "STARTUP" FROM ; DISK, ALLOWING CTL-C TO SKIP IT ; 7. OPTIONALLY ASKS FOR A PASSWORD, ALLOWING ; 5 TRIES TO GET IT RIGHT. ; 8. WHEN PASSWORD ENTERED, IF USED, DROPS ; INTO CP/M. ; 9. CALLER CAN LEAVE BY HANGING UP, ; (ANY TIME CARRIER IS LOST, IT ; WAITS 25 SECONDS, THEN GOES ; BACK TO STEP 1), OR THE CALLER ; MAY TYPE THE PROGRAM NAME (BYE) ; ; ;**************************************************** ;* OPTION CONFIGURATION SECTION * ;**************************************************** ; PRINTER EQU FALSE ;WANT TO RETAIN LIST DEVICE? DUAL$IO EQU TRUE ;WANT CONSOLE & MODEM? CALLBAK EQU FALSE ;WANT CALLBACK FEATURE? PWRQD EQU FALSE ;WANT TO USE PASSWORD? USRLOG EQU TRUE ;WANT TO COUNT NUMBER OF USERS? ACTIME EQU TRUE ;True to count activity timeouts IMSAI EQU FALSE ;ADDS VARIOUS OPIONS W/SENSE SW'S MAX$USER EQU 1 ;Highest user number supported MAX$DRIVE EQU 4 ;HIGHEST DRIVE SUPPORTED SPEED EQU 4 ;Speed in Mhz of CPU (for timing loops) TIMEOUT EQU TRUE ;WANT AUTO LOG-OFF FOR SLEEPY CALLERS? TOVALUE EQU 5 ;THIS IS Time in MINUTES TO AUTO LOGOUT WARNING EQU TRUE ;True to warn user about impending auto logout TMWARN EQU 30 ;Number of seconds before auto logout to give warning RINGS EQU 4 ;Numer of bells to give as warning (not same as CHAT) EXITFIL EQU TRUE ;True to execute a COM file on auto logout CTIME EQU 25 ;Number of seconds for carrier timeout (25 max) MAXDROP EQU 25 ;Maximum number of allowable carrier losses WELFILE EQU TRUE ;True if display of a welcome file required WELUSR EQU 0 ;USER # THAT WELCOME FILE IS KEPT IN COMFILE EQU TRUE ;WANT TO AUTOBOOT A COM FILE? COMUSR EQU 0 ;USER # THAT COMFILE IS KEPT IN DECIMAL EQU TRUE ;WANT DECIMAL VALUES FOR LOGS? CK$LWC EQU TRUE ;WANT TO TRAP LOWER CASE? RTC EQU TRUE ;True if Godbout System Support 1 MOTOR EQU TRUE ;True for motor control of drives INTER3 EQU FALSE ;True for Gobout Interfacer 3/4 I/O board FLIP EQU TRUE ;Want to swap modem mode? RETIME EQU 6 ;Time for remote modem to detect new carrier RESTART EQU TRUE ;True for trapping one RST vector RSVECT EQU 038H ;Address of restart vector to patch LENFCB EQU 12 ;Length of filename to move for LODCOM ANSTRY EQU TRUE ;True for logoff after fixed number of attempts ANSNUL EQU 8 ;Number of tries at answer nulls question ANSCASE EQU 3 ;Number of tries at answer case question ; ; if motor DISKON EQU 0H ;Turn drive motor on for YE-180 DISKOFF EQU 80H ;Turn drive motor off for YE-180 DISK EQU 0C3H ;For Godbout Disk 1 endif ;motor ; ; SPECIAL KEYS FOR SPECIAL FUNCTIONS ; FKEYS EQU TRUE ;WANT SPECIAL FUNCTION KEYS? ; ;ASSIGN FUNCTION KEYS TO THE FOLLOWING CONTROL CODES (IF USED): ; TWITKEY EQU 'N'-40H ;KEYCODE TO LOG-OUT A CREEP MSGKEY EQU 'Q'-40H ;KEYCODE TO PRINT 'MESG FROM OPER:' SYSDKEY EQU 'O'-40H ;KEYCODE TO PRINT SYS DOWN MSG ; ; FRONT-PANEL SELECTION OPTIONS ; SENSE EQU 0FFH ;SENSE SWITCH PORT NUMBER ; BLACKOUT EQU TRUE ;SWITCH TO TURN OFF REMOTE SEND HARDLOG EQU FALSE ;SWITCH TO ECHO REMOTE KBD TO PRINTER SELPASS EQU TRUE ;SWITCH TO REQUIRE A PASSWORD ; ; ASSIGNMENT OF FRONT-PANEL OPTIONS TO SWITCHES: ; LOGSW EQU 01H ;TURN ON FOR HARDCOPY PWDSW EQU 02H ;TURN ON FOR 'PASSWORD' MODE BLACKSW EQU 04H ;TURN ON TO BLACK OUT REMOTE END ENABLF EQU 08H ;TURN ON TO ENABLE SPL FUNC KEYS ; ;**************************************************** ;* END OF OPTION CONFIGURATION SECTION * ;**************************************************** ; ;ALL MODEM I/O AND CONTROL ARE HERE. ; ;************************************************ ;* * ;* 2651 Baud Rate Table * ;* * ;************************************************ ; B50 EQU 0000B ;50 bps B75 EQU 0001B ;75 bps B110 EQU 0010B ;110 bps B134 EQU 0011B ;134.5 bps B150 EQU 0100B ;150 bps B300 EQU 0101B ;300 bps B600 EQU 0110B ;600 bps B1200 EQU 0111B ;1200 bps B1800 EQU 1000B ;1800 bps B2000 EQU 1001B ;2000 bps B2400 EQU 1010B ;2400 bps B3600 EQU 1011B ;3600 bps B4800 EQU 1100B ;4800 bps B7200 EQU 1101B ;7200 bps B9600 EQU 1110B ;9600 bps B19200 EQU 1111B ;19200 bps ;************************************************ ;* * ;* 2651 Equates * ;* * ;************************************************ ; BASE EQU 05CH ;2651 base port DATA EQU BASE ;2651 data port STATUS EQU BASE+1 ;2651 status port MODE EQU BASE+2 ;2651 mode port CMMD EQU BASE+3 ;2651 command port if inter3 USER EQU BASE+7H ;UART select port CONS EQU 0 ;Console relative UART MODEM EQU 6 ;Modem relative UART endif ;inter3 ; MODE1 EQU 01101110B ;Asynch,16x,8 data bits, ; no parity, even, 1 stop bit MODE2 EQU 00110000B + B300 ;Baud rate CMMDB EQU 00100111B ;Tx enabled, RX enabled, no break ; DTR high, RTS high ; ; Status bits ; GBTBMT equ 00000001b ;Transmit buffer empty GBDAV equ 00000010b ;Data available GBTXE equ 00000100b ;Transmit shift reg empty GBPE equ 00001000b ;Parity error GBOE equ 00010000b ;Overrun error GBFE equ 00100000b ;Framing error GBCD equ 01000000b ;RS 232 Carrier Detect input GBDSR equ 10000000b ;RS 232 Data Set Ready input RING EQU GBDSR ;Ring detect input ; ; Control bits ; GBTXEN equ 00000001b ;Transmitter enable GBDTR equ 00000010b ;DTR (CCITT 108) control GBRXEN equ 00000100b ;Receiver enable GBREAK equ 00001000b ;Send break ERESET equ 00010000b ;Error reset GBRTS equ 00100000b ;RTS control (used as mode select) ; ; ORG 100H ; ;MOVE THE MODEM INTERFACE PROGRAM UP TO HI RAM ;AND JUMP TO IT. ; MOVEUP LXI B,PEND-START+1 ;NUMBER OF BYTES TO MOVE LXI H,DEST+PEND-START+1 ;END OF MOVED CODE LXI D,SOURCE+PEND-START ;END OF SOURCE CODE MVLP LDAX D ;GET BYTE DCX H ;BUMP POINTERS MOV M,A ;NEW HOME DCX D DCX B ;BUMP BYTE COUNT MOV A,B ;CHECK IF ZERO ORA C JNZ MVLP ;IF NOT, DO SOME MORE PUSH H ;SAVE FOR LATER JUMP MVI A,0C3H ;CLEAR ANY TRAPS SO SYSOP.. STA 0 ;CAN USER "BYE /A" XRA A ;NEXT WARMBOOT TO USR0/DRV A STA 4 MVI C,14 ;MAKE DRIVE A DEFAULT MOV E,A ;LOG-IN DRIVE CP/M FUNCTION CALL BDOS MVI C,32 ;GET/SET USR CP/M FUNCTION MVI E,WELUSR CALL BDOS RET ;TO ADRS PUSHED ABOVE ; VMSG: DB 'BYE version ' DB VER/10 + '0','.',(VER MOD 10) + '0',REV DB ' of ' if month = 1 DB 'January' endif if month = 2 DB 'February' endif if month = 3 DB 'March' endif if month = 4 DB 'April' endif if month = 5 DB 'May' endif if month = 6 DB 'June' endif if month = 7 DB 'July' endif if month = 8 DB 'August' endif if month = 9 DB 'September' endif if month = 10 DB 'October' endif if month = 11 DB 'November' endif if month = 12 DB 'December' endif DB ' ',DAY/10 +'0',(DAY MOD 10) + '0' DB ', 19',YEARS/10 + '0', (YEARS MOD 10) + '0',CR,LF,'$' ; SOURCE EQU $ ;BOUNDARY MEMORY MARKER ; OFFSET EQU DEST-SOURCE ;RELOC AMOUNT ;-----------------------------------------------; ; THE FOLLOWING CODE GETS MOVED ; ; TO HI RAM LOCATED AT "DEST", ; ; WHERE IT IS EXECUTED. ; ;-----------------------------------------------; ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XX C A U T I O N : IF MODIFYING ANYTHING XX ;XX IN THIS PROGRAM FROM HERE ON: XX ;XX A-L-L LABELS MUST BE OF THE FORM: XX ;XX label EQU $+OFFSET XX ;XX IN ORDER THAT THE RELOCATION TO HI RAM XX ;XX WORK SUCCESSFULLY. FORGETTING TO XX ;XX SPECIFY '$+OFFSET' WILL CAUSE THE PRO- XX ;XX GRAM TO JMP INTO WHATEVER IS CURRENTLY XX ;XX IN LOW MEMORY, WITH UNPREDICTABLE XX ;XX RESULTS. BE CAREFUL.... XX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ; ; IF CARRIER LOST, HANG UP, AWAIT RING. ; OTHERWISE, SAY GOODBYE, AND HANG UP ; START EQU $+OFFSET ; XRA A ;GET 0 STA LOSTFLG ;SHOW NO CARR. LOST STA TOUT STA BYEFLG ;Reset the "left BYE" flag ; ; DON'T ALLOW A REMOTE USER TO DO 'BYE /A' ; if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 IN STATUS ANI GBCD ;Carrier? JNZ GOODBY ;Yes, remote user so say goodbye ; ;Indentify version of program ; mvi c,printf lxi d,vmsg call bdos ; ;CHECK FOR /A OPTION ON COMMAND - REQUEST TO ;GO IMMEDIATELY INTO ANSWER MODE ; LXI H,FCB+1 ;TO OPTION MOV A,M CPI '/' ;OPTION? JNZ HANGUP ;GOT AN OPTION - VALIDATE IT INX H ;TO OPTION BYTE MOV A,M ;GET IT STA OPTION ;MIGHT NEED LATER CPI 'A' ;ANSWER? JZ ANSWER if comfile CPI 'C' JZ ANSWER endif ;comfile if usrlog ;CHECK FOR RESET OF COUNTERS CPI 'R' CZ RESET endif ;usrlog JMP HANGUP ;WE KNOW IT'S LOCAL, SO SKIP CALL TO CARCK ;NO OPTION, OR INVALID ONE NOSLASH EQU $+OFFSET CALL CARCK ;SIGNED OFF W/THIS PROG? JC HANGUP ;NOBODY THERE ; GOODBY EQU $+OFFSET UNDO EQU $+OFFSET CALL ILPRT ;PRINT THIS MSG: ; DB CR,LF,'GOOD BYE, CALL AGAIN' ; if rtc ; db CR,LF,CR,LF,'Off at ',0 ; call time endif ;RTC call ilprt ; DB CR,LF,0 ; CALL UNPATCH ;UNDO BIOS PATCHES ; ; NOBODY THERE, OR WE ARE DONE, SO HANG UP ; HANGUP EQU $+OFFSET LXI SP,STACK ;SET UP LOCAL STACK XRA A ;FORCE NEXT WARMBOOT TO USER 0 STA 4 ;AND DRIVE A MVI C,14 ;MAKE DRIVE A DEFAULT MOV E,A CALL BDOS MVI A,' ' ;DON'T ALLOW OPTIONS.. STA OPTION ;..AFTER 1 "BYE / " if comfile MVI C,32 ;GET/SET USER CODE MVI E,COMUSR ;LOCATION OF OUR COMFILE CALL BDOS CALL LODCOM ;LOAD THE COM FILE endif ;comfile if restart MVI A,0C3H ;Set up restart 7 trap STA RSVECT ; to do a warm boot XRA A STA RSVECT+1 STA RSVECT+2 endif ;restart ; ; HANGUP2 EQU $+OFFSET ; if motor CALL DSKOFF endif ;motor ;CLEAR DTR CAUSING PHONE TO HANG UP AND RESET BAUD ;RATE ON USART IN CASE IT GOT CHANGED if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 MVI A,MODE1 OUT MODE MVI A,MODE2 OUT MODE MVI A,GBRTS ;Turn off DTR, Tx and Rx enable, break, OUT CMMD ; reset and test modes (but not RTS) push b mvi b,10 ;1 second delay OFFTI EQU $+OFFSET call delay dcr b jnz offti pop b mvi a,cmmdb ;Enable Tx, Rx, DTR, RTS out cmmd MVI A,0C3H ;CLEAR ANY TRAPS.. STA 0 ;..LEFT FROM COM FILE XRA A STA DROPOUT ;Initialise count of carrier losses ; ; AWAIT RINGING ; ;CHECK LOCAL KEYBOARD FOR CTL-C EXIT REQUEST. ;NOTE: MUST DO DIRECT INPUT BECAUSE CBIOS PATCHES ;ARE NOT DONE UNTIL CALL COMES IN. ; RINGWT EQU $+OFFSET CALL UCSTS ANI 7FH ;STRIP PARITY BIT CPI 'C'-40H ;CONTROL C? if motor CZ DSKON endif ;motor if NOT USRLOG JZ 0 ;YES, --EXIT-- TO CP/M endif ;NOT USRLOG ; if USRLOG ;PRINT OUT USER INFO cz usrchk endif ;USRLOG ; ;SETUP MODEM ; ANSWER EQU $+OFFSET if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 MVI A,CMMDB ;TURN ON OUT CMMD ;..DTR CALL DELAY ;GIVE TIME FOR ANSWER CALL UCSTS ;CLEAR LOCAL CONSOLE IN DATA ;CLEAR MODEM PORT CALL MRESET ;Reset any modem UART errors CALL CARCK ;LOOK FOR CARRIER JC HANGUP2 ;Not found CALL PATCH ;PATCH JMP TABLE JMP WELCOME ; ; Get the console status when unpatched ; UCSTS EQU $+OFFSET MVI C,DIRECTIO ;DIRECT I/O CALL WILL RETURN MVI E,0FFH ;ASK FOR INPUT CALL BDOS ;A=0 IF NO CHAR WAITING RET ; ; ;FOLLOWING ARE THE USRLOG ROUTINES ; if usrlog ;INCLUDE RESET FUNCTIONS RESET EQU $+OFFSET ;RESET ALL LOGON COUNTERS lxi h,0 endif ;usrlog if usrlog shld ATTUSR ;RESET ATTEMPT COUNTER endif ;usrlog if usrlog shld NEWUSR ;RESET LOGON COUNTER endif ;usrlog if usrlog and actime shld INACT ;Reset inactivity logout timer endif ;usrlog and actime if usrlog and imsai mvi a,0ffh OUT SENSE ;RESET IMSAI PANEL DISPLAY endif ;usrlog and imsai if usrlog RET endif ;usrlog ; MCBOOT equ $+offset jmp mboot ; ;See comments above, PRNLOG must begin here ; PRNLOG EQU $+OFFSET ; if usrlog ;PRINT # OF LOGON ATTEMPTS MVI C,printf LXI D,ATMSG CALL BDOS lxi h,ATTUSR+1 ;point to high byte CALL HXOUT endif ;usrlog ; if usrlog ;PRINT # OF LOGONS MVI C,printf LXI D,SUMSG CALL BDOS lxi h,newusr+1 CALL HXOUT endif ;usrlog if usrlog and actime MVI C,printf ;Print number of inactivity timeouts LXI D,ACTMSG CALL BDOS lxi h,INACT+1 CALL HXOUT endif ;usrlog and actime RET if usrlog USRCHK equ $+offset call prnlog ;give info mvi c,printf lxi d,rs1msg call bdos ;prompt for resume bye PRNREL equ $+offset call ucsts ;get reply ora a jz prnrel cpi 'R' ;R for resume? jz prnres ;yes cpi 'R'+20H ;lower case also jnz 0 ;no, warm boot PRNRES equ $+offset mvi c,printf lxi d,rs2msg jmp bdos ;resume via bdos after message ; ;BOPLOG increments the 16 bit counter pointed to by HL ;If decimal switch is active, number is kept as 4 BCD digits ; BOPLOG equ $+offset mov a,m ;get low byte adi 1 endif ;usrlog if usrlog and decimal daa endif ;usrlog and decimal if usrlog mov m,a ;replace low order rnc ;if no carry, BOP done inx h ; else carry to high byte mov a,m ;get high byte adi 1 endif ;usrlog if usrlog and decimal daa endif ;usrlog and decimal if usrlog mov m,a ;replace high byte ret endif ;usrlog ; if usrlog ATMSG EQU $+OFFSET DB CR,LF,'Attempted Logons : $' endif ;usrlog if usrlog SUMSG EQU $+OFFSET DB CR,LF,'Successful Logons : $' endif ;usrlog if usrlog and actime ACTMSG EQU $+OFFSET DB CR,LF,'Activity Timeouts : $' endif ;usrlog and actime if usrlog RS1MSG equ $+offset DB CR,LF,CR,LF,'Type R to Resume,' DB ' anything else to Warm Boot: $' RS2MSG equ $+offset DB 'Resuming . . .',CR,LF,CR,LF,'$' endif ;usrlog if usrlog HXOUT EQU $+OFFSET push h ;save pointer call hxhaf ;do high byte first pop h dcx h ;point to low byte HXHAF equ $+offset mov a,m MOV B,A ;SAVE NUMBER RAR ;ROTATE RIGHT 4 BITS RAR ;TO MAKE AN ASCII DIGIT RAR RAR CALL ONEOUT ;OUTPUT MSH TO CONSOLE MOV A,B ;GET NUMBER BACK ONEOUT EQU $+OFFSET ANI 0FH ;GET LSH FOR OUTPUT adi 90h daa aci 40h daa PUSH B MVI C,02H MOV E,A ;OUTPUT THE NUMBER CALL BDOS POP B RET endif ;usrlog ; ;WELCOME TO THE SYSTEM ; WELCOME EQU $+OFFSET ; if usrlog ;COUNT # OF LOGON ATTEMPTS lxi h,ATTUSR ;GET # OF ATTEPMTS call boplog ;ADD THIS CALL endif ;usrlog ; if anstry MVI A,ANSNUL+1 ;SET UP COUNT FOR MAX ANSWER TRIES STA COUNT endif ;anstry GETNULL EQU $+OFFSET if anstry LDA COUNT DCR A ;Max number of tries? JZ UNDO ;Yes, exit STA COUNT ;No endif ;anstry if motor CALL DSKON endif ;motor CALL ILPRT ;PRINT THIS MSG: ; DB CR,LF DB 'HOW MANY NULLS (0-9) DO YOU NEED? ',0 ; CALL MINPUT ;GET VALUE MOV C,A CALL MOUTPUT ;ECHO CHAR MOV A,C CPI '0' JC GETNULL ;BAD, RETRY CPI '9'+1 JNC GETNULL ;BAD SUI '0' ;MAKE BINARY STA NULLS ;SAVE COUNT ; if ck$lwc if anstry MVI A,ANSCASE+1 STA COUNT endif ;anstry GETULC EQU $+OFFSET if anstry LDA COUNT DCR A ;Max number of tries? JZ UNDO ;Yes, exit STA COUNT ;No endif ;anstry CALL ILPRT ;NOW, PRINT THIS MSG: ; DB CR,LF DB 'CAN YOUR TERMINAL DISPLAY LOWER CASE? ',0 ; MVI A,20H ;FORCE CASE CONVERSION FOR NOW STA ULCSW CALL MINPUT ;GET Y OR N MOV C,A CALL MOUTPUT ;ECHO MOV A,C CPI 'N' JZ DONEOPT ;WE'RE ALREADY SET UP FOR NO LWR CASE CPI 'Y' JNZ GETULC ;WASN'T Y OR N...ASK HIM AGAIN XRA A STA ULCSW ;SET FLAG FOR NO CONVERSION ; DONEOPT EQU $+OFFSET endif ;ck$lwc ; if flip if anstry MVI A,ANSCASE+1 STA COUNT endif ;anstry FLIPMD EQU $ + OFFSET if anstry LDA COUNT DCR A ;Max number of tries? JZ UNDO ;Yes, exit STA COUNT ;No endif ;anstry CALL ILPRT ; DB CR,LF DB 'DO YOU WANT TO "FLIP" THE MODEM MODE ? ',0 ; CALL MINPUT ;GET Y OR N ANI 05FH ;Make upper case MOV C,A CALL MOUTPUT ;ECHO MOV A,C CPI 'N' ;NO? JZ DONEFLP ;OK, NO CHANGE CPI 'Y' JNZ FLIPMD ;WASN'T Y OR N...ASK HIM AGAIN CALL ILPRT ; DB CR,LF,CR,LF DB 'If you answer "Y" to the next question you have 20 seconds to',CR,LF DB 'switch your modem to the "ANSWER" mode. If you change mode',CR,LF DB 'now, you CAN''T change back until you get to CP/M command',CR,LF DB 'level.' DB CR,LF,0 ; if anstry MVI A,ANSCASE+1 STA COUNT endif ;anstry FLIPLP EQU $ + OFFSET if anstry LDA COUNT DCR A ;Max number of tries? JZ UNDO ;Yes, exit STA COUNT ;No endif ;anstry CALL ILPRT ; DB CR,LF DB 'DO YOU WANT TO CHANGE TO "ANSWER" MODE ? ',0 ; CALL MINPUT ;GET Y OR N ANI 05FH ;Make upper case MOV C,A CALL MOUTPUT ;ECHO MOV A,C CPI 'N' ;NO? JZ NOCHNG ;OK, NO CHANGE CPI 'Y' JNZ FLIPLP ;WASN'T Y OR N...ASK HIM AGAIN ; ;SET MODEM FOR DTR ON & ORIGINATE ; if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 IN CMMD ;Get the current mode XRI GBRTS ;Toggle the bit OUT CMMD ;Flip the mode CALL CARCK ;Wait for carrier MVI B,RETIME*10 FLLOOP EQU $ + OFFSET CALL DELAY ;Let remote modem detect carrier DCR B ;Remote modem ready yet? JNZ FLLOOP ;No CALL ILPRT ;Yes ; DB CR,LF,CR,LF DB 'If you see this, the mode change was successful.' DB CR,LF,0 ; JMP DONEFLP ; NOCHNG EQU $ + OFFSET CALL ILPRT ; DB CR,LF,CR,LF DB 'OK, NO CHANGE IN MODE',CR,LF,0 ; DONEFLP EQU $ +OFFSET endif ;flip ; CALL ILPRT ; DB CR,LF,CR,LF,0 ; ;PRINT THE WELCOME FILE ; if welfile LXI H,WELFILN ;SOURCE LXI D,FCB ;DESTINATION MVI B,13 ;LENGTH CALL MOVE ;MOVE THE NAME ;SET DMA ADDR TO 80H LXI D,80H MVI C,STDMA CALL BDOS ; ;SET USER FOR WELCOME FILE MVI C,32 MVI E,WELUSR CALL BDOS ; ;OPEN THE WELCOME FILE LXI D,FCB MVI C,OPEN CALL BDOS ;DID IT EXIST? INR A ;A=> 0 MEANS "NO" JZ PASSINT ;NO WELCOME FILE ;GOT A FILE, TYPE IT XRA A ;GET 0 STA FCBRNO ;ZERO RECORD # LXI H,100H ;GET INITIAL BUFF POINTER ;TYPE THE WELCOME FILE WELTYLP EQU $+OFFSET CALL RDBYTE ;GET A BYTE CPI 1AH ;EOF? JZ PASSINT ;YES, DONE MOV C,A ;SETUP FOR TYPE CALL MOUTPUT ;TYPE THE CHAR CALL MSTAT ;CHECK FOR.. ORA A ;CHAR TYPED? JZ WELTYLP ;..NO, LOOP CALL MINPUT ;..YES, GET CHAR CPI 'C'-40H ;CTL-C? JNZ WELTYLP ;..NO, LOOP UNTIL EOF endif ;welfile ; ;GET THE PASSWORD ; PASSINT EQU $+OFFSET ; ; if pwrqd and imsai and selpass IN SENSE ;TURN THE SWITCH UP.. ANI PWDSW ;..TO REQUIRE THE PASSWORD JZ NOPASS endif ;pwrqd and imsai and selpass if pwrqd MVI D,5 ;5 TRIES AT PASSWORD PASSINP EQU $+OFFSET CALL ILPRT ; DB CR,LF,'ENTER PASSWORD: ',0 ; LXI H,PASSWD ;POINT TO PASSWORD MVI E,0 ;NO MISSED LETTERS if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 IN DATA ;CLEAR OUT GARBAGE PWMLP EQU $+OFFSET CALL MINPUT ;GET A CHAR CPI 60H ;LOWER CASE? JC NOTLC ;NO, ANI 5FH ;MAKE UPPER CASE ALPHA if dual$io push psw ;save chararcter cpi ' ' ;control? jnc pwdis ;no, display it mvi c,'^' ;yes, prefix it call conout pop psw push psw adi 40h pwdis equ $+offset mov c,a call conout pop psw endif ;dual$io cpi 'U'-40h ;Control-U? jz passinp ;Yes, another try CMP M ;MATCH PASSWORD? JZ PWMAT ;..YES MVI E,1 ;..NO, SHOW MISS CPI CR ;C/R? JNZ PWMLP ;..NO, WAIT FOR C/R ; ;PASSWORD DIDN'T MATCH ; PWNMAT EQU $+OFFSET CALL ILPRT ; DB '++INCORRECT++',CR,LF,0 ; DCR D ;MORE TRIES? JNZ PASSINP ;YES JMP BADPASS ;NO, GO HANG UP ; ;CHARACTER MATCHED IN PASSWORD ; PWMAT EQU $+OFFSET INX H ;TO NEXT CHAR CPI CR ;END? JNZ PWMLP ;..NO, LOOP ;END OF PASSWORD. ANY MISSED CHARS? MOV A,E ;GET FLAG ORA A JNZ PWNMAT ;NOT RIGHT ;PASSWORD CORRECT endif ;pwrqd NOPASS EQU $+OFFSET if rtc call ilprt ; db CR,LF,CR,LF,'On system at ',0 ; call time call ilprt ; db CR,LF,0 ; endif ;rtc if usrlog ;COUNT # OF SUCCESSFUL LOGONS lxi h,NEWUSR ;GET LAST VALUE call boplog ;add one endif ;usrlog if usrlog and imsai ;DISPLAY ON IMSAI lda newusr ;re-get low order value CMA ;invert for lights OUT SENSE ;DISPLAY ON IMSAI FRONT PANEL endif ;usrlog and imsai CALL ILPRT ; ; DB CR,LF,'Please wait a moment . . .',CR,LF,CR,LF,0 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^etc ; PUT BOOT-UP MSG HERE ; if comfile MVI C,32 MVI E,COMUSR ;SWITCH TO COM FILE USER # CALL BDOS MVI A,0FFH STA BYEFLG LDA OPTION CPI 'A' ;SYSOP CAN BYPASS COM FILE BY.. JZ 0 ;..TYPING "BYE /A" CPI 'C' ;OPER CAN ALSO GO TO COM.. JNZ 100H ;..FILE LOAD WITH "BYE /C" CALL ILPRT ;PRINT THIS MESSAGE ; DB 'Loading system...',CR,LF,0 ; CALL LODCOM JMP 100H ;EVERYONE ELSE GETS COM FILE endif ;comfile if not comfile MVI A,0FFH STA BYEFLG JMP 0 endif ;not comfile ; CARCK EQU $+OFFSET ; LOSS OF CONNECTION TEST ; ;IF WE DETECT THAT THERE IS NO CARRIER UPON ENTRY TO ;THIS ROUTINE, WE'LL KEEP CHECKING FOR 25 SECONDS TO SEE IF THE ;CARRIER RETURNS. IF SO, WE'LL JUST CONTINUE ON. IF NOT, WE'LL ;SIGNAL THIS BY SETTING THE CARRY FLAG. ; if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 IN STATUS ;GET MODEM STATUS ANI GBCD ;GOT A CARRIER? JNZ CARCK2 ;YES, GO ON WITH TESTS LDA DROPOUT ;Get dropout count ADI 1 ;Increment it CPI MAXDROP ;Bad line? JZ BADPASS ;Yes, reset system STA DROPOUT ;Save for later PUSH B ;PRESERVE BC SO WE CAN USE IT MVI B,CTIME*10 ;Initialise timeout value CARLP EQU $+OFFSET CALL DELAY ;WAIT .1 SECONDS IN STATUS ANI RING ;Phone ringing? JZ NO$RING ;No MVI B,CTIME*10 ;Yes, reintialise count NO$RING EQU $+OFFSET IN STATUS ;GET MODEM STATUS ANI GBCD ;HAS CARRIER RETURNED? MOV A,B ;PRESERVE COUNTDOWN VALUE 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 B MOV B,A ;GET COUNTER VALUE IN B JMP CARLP ;KEEP CHECKING ; ; NOW TEST DRIVE #'S AND (IF CPM 2.X) ; USER #'S TO INSURE THAT MAXIMUMS ; ARE NOT EXCEEDED ; CARCK2 EQU $+OFFSET LDA 4 ;CHECK DISK/USER # ANI 0FH ;ISOLATE DRIVE CPI MAX$DRIVE ;VALID DRIVE? JC CARCK3 ;YES, SKIP THIS JUNK LDA 4 ;RESTORE WHOLE LOGIN BYTE ANI 0F0H ;RETAIN USER # STA 4 ;FORCE DRIVE TO A CALL ILPRT ;TELL USER WHAT HE DID ; DB 'INVALID DRIVE - RETURNING TO A:',0 ; JMP 0 ;FORCE WARM BOOT CARCK3 EQU $+OFFSET ; LDA 4 ;REFRESH LOGIN BYTE AGAIN ANI 0F0H ;ISOLATE USER # CPI MAX$USER*16+1 ;VALID USER #? JC CARCK4 ;YES, DON'T CHANGE LDA 4 ;GET BACK LOGIN BYTE ANI 0FH ;KEEP DRIVE, ZERO USER STA 4 CALL ILPRT ;TELL HIM WHAT HAPPENED ; DB 'INVALID USER NUMBER - RETURNING TO 0',0 ; JMP 0 ;FORCE WARM BOOT ; CARCK4 EQU $+OFFSET ORA A RET ; ; .1 SEC DELAY ROUTINE ; DELAY EQU $+OFFSET PUSH B LXI B,SPEED*4167 ;TIMING CONSTANT ; DELAY1 EQU $+OFFSET DCX B MOV A,B ORA C JNZ DELAY1 POP B RET ; ;PATCH IN THE NEW JMP TABLE (SAVING THE OLD) ; PATCH EQU $+OFFSET CALL TBLADDR ;CALC HL= CP/M JMP TABLE LXI D,VCOLDBT ;POINT TO SAVE LOCATION MVI B,18 ;ALWAYS SAVE PRINTER VECTOR CALL MOVE ;MOVE IT ;NOW MOVE NEW JMP TABLE TO CP/M CALL TBLADDR ;CALC HL=CP/M'S JMP TABLE XCHG ;MOVE TO DE LXI H,NEWJTBL ;POINT TO NEW CALL MOVE ;MOVE IT RET ; UNPATCH EQU $+OFFSET CALL TBLADDR ;HL=CP/M'S JMP TABLE XCHG ;MOVE TO DE LXI H,VCOLDBT ;GET SAVED TABLE CALL MOVE ;MOVE ORIG BACK RET ; ;CALCULATE HL=CP/M'S JUMP TABLE, B=LENGTH ; TBLADDR EQU $+OFFSET LHLD 1 ;GET BIOS POINTER DCX H ;..SKIP DCX H ;..TO DCX H ;..COLD BOOT if printer ;RETAIN LIST DEVICE? MVI B,15 ;DON'T MOVE LISTER JUMP else MVI B,18 ;BYTES TO MOVE endif ;printer RET ; ;MOVE (HL) TO (DE), LENGTH IN (B) ; MOVE EQU $+OFFSET MOV A,M ;GET A BYTE STAX D ;PUT AT NEW HOME INX D ;BUMP POINTERS INX H DCR B ;DEC BYTE COUNT JNZ MOVE ;IF MORE, DO IT RET ;IF NOT,RETURN ; ;COMMON ROUTINE TO CHECK FOR CARRIER LOST, ;CALLED FROM CONSOLE OUT ; CHECK EQU $+OFFSET CALL CARCK ;SEE IF CARRIER STILL ON RNC ;ALL OK ;CARRIER IS LOST. TYPE MESSAGE SO LOCAL CONSOLE ; SHOWS THE REASON BADPASS EQU $+OFFSET ;COME HERE ON BAD PASSWORD MVI A,1 ;SHOW CARRIER LOST SO STA LOSTFLG ;..WE WON'T CK AGAIN LXI SP,STACK ;ENSURE VALID STACK CALL ILPRT ; DB CR,LF,'++CARRIER LOST++',CR,LF,' ',0 ; CALL UNPATCH ;RESTORE ORIG BIOS JMP TBL XRA A ;CLEAR OUT CARRIER.. STA LOSTFLG ;..LOST FLAG JMP HANGUP ; ;READBYTE ROUTINE - USED TO READ THE ; WELCOME FILE ; if welfile RDBYTE EQU $+OFFSET MOV A,H ;TIME TO READ? ORA A ;..IF AT 100H JZ NORD ;NO READ REQ'D ;HAVE TO READ A SECTOR LXI D,FCB MVI C,READ CALL BDOS ORA A ;OK? MVI A,1AH ;FAKE UP EOF RNZ ;RET EOF IF BAD LXI H,80H NORD EQU $+OFFSET MOV A,M ;GET CHAR INX H ;TO NEXT RET endif ;welfile ; ;KEYBOARD/MODEM STATUS TEST ROUTINE ; MSTAT EQU $+OFFSET call check if dual$io ;WANT LOCAL CONSOLE? CALL CONSTAT ;GET LOCAL STATUS ORA A RNZ ;RET IF LOCAL CHAR endif ;dual$io ; if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 IN STATUS ;GET MODEM STATUS ANI GBDAV ;GOT A CHARACTER? RZ ;RETURN IF NOT IN STATUS ;GET MODEM STATUS ANI GBFE+GBOE ;CHECK FOR FRAMING AND OVERRUN ERROR JZ MSTAT1 ;NO ERROR, CHARACTER IS VALID CALL MRESET ;Reset modem UART errors XRA A ;RETURN FALSE RET ; MSTAT1 EQU $+OFFSET MVI A,0FFH ;SHOW READY ORA A RET ; MRESET EQU $+OFFSET IN DATA ;Swallow questionable character IN CMMD ;Get command byte ADI ERESET ;Clear Overrun & Framing errors OUT CMMD ;Reset UART ERROR SUI ERESET OUT CMMD ;Clear UART reset RET ; ;MODEM INPUT FUNCTION, CHECKS LOCAL CONSOLE FIRST ; MINPUT EQU $+OFFSET ; if timeout PUSH H LXI H,TOVALUE*MINUTES ;INITIALIZE TIMEOUT COUNTER SHLD TOCNT POP H endif ;timeout ; MINPUT1 EQU $+OFFSET LDA LOSTFLG ;KNOWN LOSS.. ORA A ;..OF CARRIER? CZ CHECK ;No, better check if carrier still there if exitfil LDA TOUT ;Timeout out? ORA A JNZ FORCED ;Yes, accept forced input endif ;exitfil CALL MSTAT ;ANYTHING? ORA A if timeout JNZ MINPUT2 CALL DELAY ;KILL 100 MS PUSH H LHLD TOCNT ;KNOCK DOWN TIMEOUT COUNTER DCX H SHLD TOCNT if warning PUSH D LXI D,10*TMWARN ;Warning time in seconds MOV A,H CMP D ;High bytes match? JNZ NOMATCH ;No MOV A,L ;Yes CMP E ;Low bytes match? JNZ NOMATCH ;No CALL DINGER ;Yes, wake up user CALL ILPRT DB '++ AUTO LOGOFF SOON ++ ',0 ; CALL DINGER ;Ring my chimes, maybe I'll come NOMATCH EQU $ + OFFSET POP D endif ;warning MOV A,H ORA L POP H JNZ MINPUT1 ;STILL TIME LEFT..KEEP TRYING CALL ILPRT ; DB CR,LF,'++ INPUT TIMED OUT ++',BEL,0 ; if usrlog and actime PUSH H lxi h,INACT call boplog ;Add 1 to inactivity timeout counter endif ;usrlog and actime if exitfil LDA BYEFLG ;Still in BYE? ORA A JZ NOSLASH ;Yes, just internal logout MVI A,0FFH ;No, send through exit file STA TOUT ;Set logout flag LXI H,CMMDSTR ;Point to start of command string SHLD CMMDPTR POP H ;Keep stack straight LHLD VWARMBT+1 ;Do a "real" warm boot PCHL ; CMMDSTR EQU $+OFFSET ;The following string get passed to CCP DB 'TIMEOUT',CR+80H ;Load up the exit program endif ;exitfil if not exitfil POP H JMP NOSLASH endif ;not exitfil else JZ MINPUT ;LOOP TILL CHAR RCD endif ;timeout ; MINPUT2 EQU $+OFFSET if dual$io ;BOTH LOCAL AND REMOTE CALL CONSTAT ;CHECK LOCAL CONSOLE ORA A ;CHAR? JNZ CONIN ;..YES, READ IT, RET. endif ;dual$io ; ; LOCAL CONSOLE WASN'T READY, SO READ MODEM ; if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 IN DATA ;GET DATA BYTE ANI 7FH ;DELETE PARITY JZ MINPUT ;IGNORE NULLS if imsai and hardlog PUSH B MOV B,A IN SENSE ANI LOGSW MOV A,B POP B JZ NOLOG endif ;imsai and hardlog if hardlog CPI 20H JNC MINPUT3 CPI CR JNZ NOLOG MINPUT3 EQU $+OFFSET CALL LISTOUT ;ECHO ON PRINTER CPI CR JNZ NOLOG ;CR NEEDS LINEFEED MVI A,LF CALL LISTOUT ;SO SEND IT MVI A,CR ;GET BACK CR endif ;hardlog ; NOLOG EQU $+OFFSET ; CPI 3 ;IS IT CONTROL-C? RNZ ;NO, PASS IT THRU LDA 0 ;SEE IF WARM BOOT DISABLED CPI 0C3H ;JMP MEANS WARM BOOT OK MVI A,3 ;SO RETURN CONTROL-C RZ XRA A ;ELSE CONVERT TO NULL RET ; if warning DINGER EQU $ + OFFSET MVI D,RINGS DING1 EQU $ +OFFSET CALL ILPRT ;Ring my chimes, maybe I'll come DB BEL,0 ; as Chuck Foresburg says... MVI E,5 ;Pause between bells DING2 EQU $ + OFFSET CALL DELAY DCR E JNZ DING2 DCR D ;Done ringing? JNZ DING1 ;No RET endif ;warning if exitfil FORCED EQU $+OFFSET push h LHLD CMMDPTR ;Get pointer into command string MOV A,M ;Get a byte from the string CPI CR+80H ;Bit 7 set high? (terminates) JZ FDONE ;Yes INX H ;No, adjust pointer SHLD CMMDPTR ;Save for next time pop h RET ;Give CCP the character ; FDONE EQU $+OFFSET pop h PUSH PSW XRA A STA TOUT ;Reset the flag POP PSW ANI 07FH RET endif ;exitfil ; ; MOUTPUT EQU $+OFFSET ;IF WE ALREADY KNOW CARRIER IS LOST, ;DON'T CHECK FOR IT AGAIN LDA LOSTFLG ;KNOWN LOSS OF CARRIER? ORA A jnz silent ;avoid loop in case carrier lost call CHECK ;CARRIER STILL ON? lda tout ;Forced timeout? ora a jnz silent ;Yes, don't let user see what happens if inter3 mvi a,modem out user ;Select modem UART endif ;inter3 IN STATUS ;GET MODEM STATUS ANI GBTBMT ;TRANSMIT REGISTER EMPTY? JZ MOUTPUT ;LOOP IF NOT READY if imsai and blackout and dual$io IN SENSE ;FLIP SWITCH UP... ANI BLACKSW ;..TO BLIND REMOTE USER JNZ SILENT endif ;imsai and blckout and dual$io MOV A,C ;GET CHAR ANI 7FH ; if ck$lwc CPI 60H ;CHECK FOR LOWER CASE JC MOUTP2 ;SKIP IF NOT LC CPI 7FH ;CHECK FOR RUBOUT JZ MOUTP2 PUSH H LXI H,ULCSW ;SUBTRACT EITHER 20H OR 0 SUB M POP H MOV C,A ;FORCE ON LOCAL AS WELL AS REMOTE MOUTP2 EQU $+OFFSET endif ;ck$lwc ; OUT DATA ;OUTPUT TO MODEM SILENT EQU $+OFFSET ; if dual$io ;TO LOCAL ALSO? push psw CALL CONOUT ;SEND TO REGULAR BIOS pop psw endif ;dual$io ; ;CHECK FOR NULLS ; CPI LF ;TIME FOR NULLS? RNZ ;NO, RETURN ;SEND NULLS IF REQUIRED LDA NULLS ;GET COUNT ORA A ;ANY? RZ ;..NO PUSH B MOV B,A ;SAVE COUNT MVI C,0 ;0 IS A NULL NULLP EQU $+OFFSET CALL MOUTPUT ;TYPE A NULL DCR B ;MORE? JNZ NULLP ;..YES, LOOP POP B RET ; ; BOOT TRAP-BECOMES DISCONNECT IF ; JMP AT 0 HAS BEEN ALTERED ; MBOOT EQU $+OFFSET LDA 0 ;LOOK AT OPCODE CPI 0C3H ;IS IT STILL JMP? JZ VWARMBT ;YES, ALLOW IT JMP NOSLASH ;NO, DISCONNECT ; ; INLINE PRINT ROUTINE ; CALL ILPRT ; DB 'MSG',0 ; ILPRT EQU $+OFFSET XTHL ;SAVE HL, GET MSG PUSH B ;SAVE ILPLP EQU $+OFFSET MOV C,M ;GET CHAR CALL MOUTPUT ;OUTPUT IT INX H ;POINT TO NEXT MOV A,M ;TEST ORA A ;..FOR END JNZ ILPLP POP B ;RESTORE XTHL ;RESTORE HL, RET ADDR RET ;RET PAST MSG ; IF pwrqd ;KEEP PASSWORD HERE ;ACCESS PASSWORD (ENDS IN C/R) ; PASSWD EQU $+OFFSET DB 'PLAUGER' ;THE PASSWORD ITSELF DB CR ;END OF PASSWORD ;ALLOW ROOM FOR BIGGER PASSWORD TO BE ; PATCHED IN DB 0,0,0,0,0,0,0,0,0,0,0 endif ;pwrqd ; ; ROUTINE TO LOAD THE COM FILE ; if comfile LODCOM EQU $+OFFSET XRA A ;INITIALIZE FCB STA COMFCB LXI H,COMFCB+12 MVI B,21 ZLOOP EQU $+OFFSET MVI M,0 INX H DCR B JNZ ZLOOP MVI C,OPEN ;NOW OPEN THE FILE LXI D,COMFCB CALL BDOS INR A ;SHOULD BE NON-ZERO JZ ABORT ;NO FILE, ABORT ; ; NOW LOAD THE FILE ; LHLD 6 ;GET TOP OF MEMORY LXI D,-80H ;RECORD LOADS CAN'T START.. DAD D ;..ABOVE (BDOS) - 80H 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 EQU $+OFFSET POP D ;GET TPA ADRS LXI H,80H ;POINT TO NXT ADRS 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 ;RE-SAVE FOR NEXT TIME ; MOV A,E ;SUBTRACT: (TOP) - (ADRS) SUB L MOV A,D ;ONLY THE CARRY NEEDED SBB H ; JNC SIZEOK ;CY= BETTER MOVCPM CALL ERRXIT ;SO TELL THE STORY ; DB '++ PROGRAM AREA TOO SMALL ++','$' ;; SIZEOK EQU $+OFFSET INX B PUSH B PUSH H ;SAVE TPA ADRS XCHG ;ALIGN REGISTERS MVI C,STDMA ;TELL BDOS WHERE TO PUT RECORD CALL BDOS LXI D,COMFCB ;NOW READ THE RECORD 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 CALL LOADOK ;PRINT THIS MSG TO CONSOLE: ; DB '++ COM FILE LOADED ++',CR,LF,'$' ; LOADOK EQU $+OFFSET POP D LDA OPTION ;SEE IF THIS WAS "BYE /C" CPI 'C' ;IF IT WAS THEN.. RZ ;..DON'T PRINT MESSAGE MVI C,PRINTF CALL BDOS RET ; ABORT EQU $+OFFSET CALL ERRXIT ; DB CR,LF,'+++CANNOT FIND COM FILE+++','$' ; ERRXIT EQU $+OFFSET POP D MVI C,PRINTF CALL BDOS ;PRINT THE ABORT MSG JMP 0 ;GIVE UP endif ;comfile ; ;THIS AREA IS USED FOR VECTORING CALLS TO THE ;USER'S CBIOS, BUT SAVING THE REGISTERS FIRST ;IN CASE THEY ARE DESTROYED. ; CONSTAT EQU $+OFFSET PUSH B PUSH D PUSH H CALL VCONSTAT POP H POP D POP B RET ; CONIN EQU $+OFFSET PUSH B PUSH D PUSH H CALL VCONIN if fkeys CALL CKFUNC endif ;fkeys POP H POP D POP B RET ; CKFUNC EQU $+OFFSET ; if fkeys and imsai PUSH B MOV B,A ;SAVE CHAR IN SENSE ;READ THE SWITCHES ANI ENABLF ;CHECK FKEY ENAB SW MOV A,B POP B RZ ;NO FUNCT IF SW OFF endif ;fkeys and imsai ; if fkeys CPI SYSDKEY JZ SYSDOWN ;TELL CALLER TO LEAVE CPI TWITKEY JZ GOODBY ;MAKE CALLER LEAVE CPI MSGKEY RNZ CALL ILPRT ;SEND CALLER A MESSAGE ; DB 'MESSAGE FROM OPERATOR:',0 ; MVI A,' ' ;SOMETHING TO RETURN WITH RET ; SYSDOWN EQU $+OFFSET CALL ILPRT ; DB 'SYSTEM DOWN IN' DB ' 5 MINUTES....',0 ; MVI A,' ' RET endif ;fkeys ; CONOUT EQU $+OFFSET PUSH B PUSH D PUSH H CALL VCONOUT POP H POP D POP B RET ; if hardlog LISTOUT EQU $+OFFSET PUSH B PUSH D PUSH H PUSH PSW MOV C,A CALL VLISTOUT POP PSW POP H POP D POP B RET endif ;hardlog ; ; ; THIS IS THE JMP TABLE WHICH IS COPIED ; ON TOP OF THE ONE POINTED TO BY ; LOCATION 1 IN CP/M ; NEWJTBL EQU $+OFFSET JMP MCBOOT ;COLD BOOT JMP MBOOT ;WARM BOOT JMP MSTAT ;MODEM STATUS TEST JMP MINPUT ;MODEM INPUT ROUTINE JMP MOUTPUT ;MODEM OUTPUT ROUTINE RET ;DUMMY LIST DEVICE NOP NOP ; if motor ; DSKON EQU $+OFFSET PUSH PSW ;SAVE THE A AND FLAGS MVI A,DISKON ;VALUE TO TURN ON MOTORS OUT DISK ;TO THE DISK CONTROLLER PUSH H ;THIS IS TIMER LXI H,0 ;THIS LONG DSKLP EQU $+OFFSET XTHL XTHL DCX H ;COUNT LOOP MOV A,H ;CHECK FOR DONE ORA L JNZ DSKLP POP H ;RESTORE HL POP PSW ;AND A & FLAGS RET ; DSKOFF EQU $+OFFSET PUSH PSW ;SAVE A & FLAG MVI A,DISKOFF ;VALUE TO TURN MOTORS OFF OUT DISK POP PSW RET ; endif ;motor ; if rtc CLKBASE EQU 50H ;BASE OF SYSTEM SUPPORT 1 CARD CLKCTL EQU CLKBASE+10 ;CLOCK CONTROL PORT CLKDATA EQU CLKBASE+11 ;CLOCK DATA PORT CREAD EQU 10H+40H ;READ COMMAND + HOLD COUNT COMMAND ; TIME EQU $+OFFSET PUSH H PUSH D PUSH B PUSH PSW MVI D,CREAD+5 ;POINT TO 10s OF HOURS MVI B,3 ;3 LOOPS JMP TX ;START W/ NO SEPARATOR ; T1 EQU $+OFFSET MVI C,':' ;SEPARATOR CALL MOUTPUT ;TO THE PRINTER TX EQU $+OFFSET MOV A,D ;GET THE DIGIT ADDRESS CALL CLOCK ;GET THE VALUE MOV C,A ;SAVE IT MVI A,CREAD+5 ;TEST FOR FIRST LOOP CMP D ;1ST LOOP? MOV A,C ;RECOVER THE VALUE JNZ T2 ;JUMP IF NOT 1ST LOOP ANI 3 ;DROP PM INDICATOR T2 EQU $+OFFSET ADI '0' ;ADD ASCII BIAS MOV C,A CALL MOUTPUT ;AND PRINT IT DCR D ;POINT TO NEXT DIGIT MOV A,D ;GET THE DIGIT ADDRESS TO A CALL PCLOCK ;GET & PRINT ASCII DCR D ;BUMP DIGIT COUNTER DCR B JNZ T1 ;LOOP TILL ALL PRINTED ; ; CALL ILPRT ;PRINT THE TIME ZONE ; DB ' EST ',0 ;Australian EST ; ; WE WILL NOW PRINT THE DAY OF THE WEEK, FOLLOWED ; BY THE MONTH, DATE AND YEAR ; ; MVI A,CREAD+6 ;THIS IS DAY OF WEEK CALL CLOCK ;GET THE DAY NUMBER ; DAYDONE EQU $+OFFSET ADD A ;DOUBLE DAY COUNT LXI H,DAYS ;POINT TO TABLE MOV E,A ;ADD OFFSET TO DE MVI D,0 DAD D ;NEW POINTER IN HL MOV A,M ;GET LO BYTE OF WORD INX H ;POINT TO HI BYTE MOV H,M ;TO H MOV L,A ;PLUS LO BYTE POINTS TO STRING CALL LINOUT ;PRINT THE DAY ; MVI A,CREAD+10 ;10s OF MONTHS CALL CLOCK ORA A ;WE GOT 10's OF MONTHS? JZ NOTENS ;JUMP IF NOT MVI A,10 ;ADD 10s IF WE GOT EM NOTENS EQU $+OFFSET MOV B,A ;SAVE 10s IN B MVI A,CREAD+9 ;GET THE ONES CALL CLOCK ADD B ;ADD TO THE 10s PLACE TO GET MONTH DCR A ;CORRECT FOR JAN=1 ADD A ;DOUBLE MONTH NUMBER LXI H,MONTHS ;POINT TO DISPATCH TABLE MOV E,A ;OFF SET TO DE MVI D,0 DAD D ;POINTER TO STRING AT (HL) MOV A,M ;GET LO BYTE TO A INX H ;POINT TO NEXT MOV H,M ;HI BYTE TO H MOV L,A ;LO BYTE TO L POINTS TO STRING CALL LINOUT ;PRINT THE MONTH ; MVI A,CREAD+8 ;10s OF DAYS CALL CLOCK ANI 3 ;DROP LEAP YEAR INDICATOR JZ NTENS ;JUMP IF NO TENS PLACE CALL PASC ;PRINT IT NTENS EQU $+OFFSET MVI A,CREAD+7 ;ONES OF DAYS CALL PCLOCK ;PRINT THEM LXI H,YEAR ;PLUS YEAR MESSAGE CALL LINOUT ;TO LISTER MVI A,CREAD+12 ;TENS OF YEAR CALL PCLOCK ;PRINT THEM MVI A,CREAD+11 ;ONES OF YEAR CALL PCLOCK CALL ILPRT ;FINISH THE LINE ; DB CR,LF,0 ; POP PSW POP B POP D POP H RET ; PCLOCK EQU $+OFFSET CALL CLOCK ;GET THE DIGIT PASC EQU $+OFFSET ADI '0' ;ADD ASCII BIAS MOV C,A JMP MOUTPUT ;AND PRINT ; CLOCK EQU $+OFFSET OUT CLKCTL ;TELL IT ADDRESS IN CLKDATA ;GET THE DATA NYBBLE PUSH PSW ;SAVE THE DATA XRA A ;GET 0 OUT CLKCTL ;RESET HOLD BIT POP PSW ;RESTORE DATA RET ; LINOUT EQU $+OFFSET MOV A,M ;GET THE CHARACTER CPI '$' ;DONE? RZ ;RETURN IF DONE MOV C,A ;ELSE PRINT IT CALL MOUTPUT INX H ;POINT TO NEXT CHARACTER JMP LINOUT ;THEN LOOP TILL DONE ; ; SUN EQU $+OFFSET DB 'Sunday, $' MON EQU $+OFFSET DB 'Monday, $' TUE EQU $+OFFSET DB 'Tuesday, $' WED EQU $+OFFSET DB 'Wednesday, $' THU EQU $+OFFSET DB 'Thursday, $' FRI EQU $+OFFSET DB 'Friday, $' SAT EQU $+OFFSET DB 'Saturday, $' ; JAN EQU $+OFFSET DB 'January $' FEB EQU $+OFFSET DB 'February $' MAR EQU $+OFFSET DB 'March $' APR EQU $+OFFSET DB 'April $' MAY EQU $+OFFSET DB 'May $' JUN EQU $+OFFSET DB 'June $' JUL EQU $+OFFSET DB 'July $' AUG EQU $+OFFSET DB 'August $' SEP EQU $+OFFSET DB 'September $' OCT EQU $+OFFSET DB 'October $' NOV EQU $+OFFSET DB 'November $' DEC EQU $+OFFSET DB 'December $' ; YEAR EQU $+OFFSET DB ', 19$' ; ;################################################# DAYS EQU $+OFFSET DW SUN DW MON DW TUE DW WED DW THU DW FRI DW SAT DW SUN ; MONTHS EQU $+OFFSET DW JAN DW FEB DW MAR DW APR DW MAY DW JUN DW JUL DW AUG DW SEP DW OCT DW NOV DW DEC ; ; endif ;RTC ; if welfile WELFILN EQU $+OFFSET DB 0,'STARTUP ',0 ;WELCOME FILE NAME ^^^^^^^^^^^ endif ;welfile ; NULLS EQU $+OFFSET DB 5 ; if comfile COMFCB EQU $+OFFSET DB 0,'ENTRBBS COM' ;COM FILE NAME ^^^^^^^^^^^ endif ;comfile PEND EQU $+OFFSET ;END OF RELOCATED CODE ; ; THESE AREAS ARE NOT INITIALIZED ; DS 21 ;REST OF COM FCB ULCSW EQU $+OFFSET DS 1 OPTION EQU $+OFFSET DS 1 TOCNT EQU $+OFFSET DS 2 ; ;KEEP TRACK OF LOST CARRIER WHEN TYPING ;"++CARRIER LOST++" SO WE DON'T LOOP ; LOSTFLG EQU $+OFFSET DS 1 DROPOUT EQU $+OFFSET DS 1 ; ;These are for the timeout exit routine ; if exitfil TOUT EQU $+OFFSET DS 1 BYEFLG EQU $+OFFSET DS 1 CMMDPTR EQU $+OFFSET DS 2 endif ;exitfil ; ;Counter for number of tries at answering questions ; if anstry COUNT EQU $+OFFSET DS 1 endif ;anstry ; ;SAVE THE CP/M JUMP TABLE HERE ; VCOLDBT EQU $+OFFSET DS 3 VWARMBT EQU $+OFFSET DS 3 VCONSTAT EQU $+OFFSET DS 3 VCONIN EQU $+OFFSET DS 3 VCONOUT EQU $+OFFSET DS 3 VLISTOUT EQU $+OFFSET DS 3 ; ; SINCE THESE AREAS ARE NOT INITIALIZED, ; THE FOLLOWING COUNTERS WILL NOT BE CHANGED ; BY SUBSEQUENT LOADS OF THIS PROGRAM ; if usrlog ATTUSR EQU $+OFFSET DS 2 NEWUSR EQU $+OFFSET DS 2 NONUSR EQU $+OFFSET DS 2 INACT EQU $+OFFSET DS 2 endif ; ; DS 60 STACK EQU $+OFFSET ;LOCAL STACK ; ENDMARK EQU $+OFFSET ;! IGNORE ERROR. THIS MARKS END OF PGM ; CI EQU 1 WRCON EQU 2 DIRECTIO EQU 6 PRINTF EQU 9 CSTS EQU 11 DRESET EQU 13 OPEN EQU 15 READ EQU 20 STDMA EQU 26 FCB EQU 5CH FCBRNO EQU FCB+32 ; END