; BYE V6.9 ; REMOTE CONSOLE PROGRAM FOR CP/M AND MODEM ; ;--------------------------------------------------------------- ; This version of BYE is contributed to CP/M-Net 'as-is'. ; It has been hacked for Australian conditions, where ; autodial and auto answer are illegal. The Bell-103 ; modem equates have also been removed. ; Nevertheless It shows how CDOS can be configured by BYE ; as an RCPM host DOS. ; The table patching routines shown here effectively enable/disable ; the printer and allow remote access to the DOS ; ; Sorry about the hacking folks.. ; If you need any help contact Trevor Marshall, ; 26 Mirrelia Way, ; Ferndale, West Australia 6155. ; ; ps. If anyone manages to get INFOSOFT IOS to work with this pgm ; please let me know. I have ascertained that although IOS ; is table driven identiaccly to CDOS (the table information ; came from INFOSOFT) it pulls the vector addresses in during ; initialization rather than every time a call is made and ; although this makes it faster it will not operate with this BYE. ; Maybe there is an undocumented system call or something??? ; 14 July 1981 ;----------------------------------------------------------------- ;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. ;The following had a hand in its development: ; Bill Precht, Hank Syzszka, P.L.Kelley, Bruce Ratoff,David Kozinn ; ,Ron Fowler, Dave Hardy, Bruce Levison, Keith Petersen and Robbin Hough. ; before Trevor Marshall reworked it for CDOS and IOS. ;For further background information see the file 'BYE69.ASM'. ; ;------------------------------------------------ ; ;This program runs up in high RAM. It gets there ;by being moved there when 'BYE' is typed. ; ;The program in high 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 (see callback routines) ; 4. Awaits incoming carrier going to step 1 ; if none found in 15 seconds ; 5. Asks number of nulls (0-9) ; 6. Types the file "WELCOME" from ; disk, allowing CTL-C to skip it ; 7. Asks for a password, allowing ; 5 tried 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 15 seconds, then goes ; back to step 1), or the caller ; may type the program name (BYE) ; ;------------------------------------------------ ; The original BYE programs will not work with CDOS (IOS) because ; they do not use the bios jump table for internal calls to I/O. ; Instead they are table driven, by an SDVT whick looks like: ; SDVT DW CON,TERM,RDR,PUN,LIST,CLOCK ; which in turn vectors to tables such as the console I/O ; CON DW CINIT,CSTAT,CINDATA,CRDY,COUTDATA ; and list ; LIST DW LINIT,LRDY,LOUT ; ; These tables are patched to vector to our modem BIOS. ; We can locate them by using the 81H system BDOS call ; which returns a user register pointer in BC ; (BC) -> URREG (2) ; SCHSW (1) ; SDVT (2) ; SDT (2) ; SYSBOT(2) ; OPILINK (2) ; and so we can calculate the SDVT address. ; ; For further information (or bug info) contact ; Trevor Marshall ; Wait-Aid,West Aust Inst Tech, ; Hayman Rd, Bentley, Western Australia 6102 ; or ring (09) 457 6059 any time. ; ;------------------------------------------------------- ; ; ;System equates ; FALSE EQU 0 TRUE EQU NOT FALSE ; CR EQU 0DH LF EQU 0AH MINUTES EQU 20*60 ;CONSTANT FOR 1 MIN TIME DELAY ; ;Change the following equate to an area in your ;high memory where this program may patch itself in. ;Approximate memory requirements: 2k bytes or more, ;depending upon the options selected. A marker has ;been placed at the end to deliberately print an error ;message during assembly in order to determine the actual ;ending address of the program. The error message will ;not affect the assembly. Make sure you have memory ;available up to the address shown. ; DEST EQU 0EA00H ;RUNNING LOCATION OF CODE ; CDOS EQU TRUE ;If running CDOS or IOS ; TREVORS EQU TRUE ;True for my design ; ; ;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'. ; ;**************************************************** ;* 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 FALSE ;WANT TO COUNT NUMBER OF USERS? HARDLOG EQU FALSE ;WANT TO ECHO REMOTE KBD TO PRINTER? MAXDRV EQU 1 ;HIGHEST DRIVE SUPPORTED FASTCLK EQU TRUE ;SET TRUE FOR 4 MHZ CLOCK TIMEOUT EQU FALSE ;WANT AUTO LOG-OFF FOR SLEEPY CALLERS? TOVALUE EQU 7 ;THIS IS 7 MINUTES TO AUTO LOGOUT 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? TRAPLC EQU TRUE ;WANT TO TRAP LOWER CASE? ; ;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 ; ; ;**************************************************** ;* End of option configuration section * ;**************************************************** ; ;All modem I/O and control are here ; ;************ Trevor's modem I/O area ************ ; IF TREVORS ; ; USART is Intel 8251 or equivalent ; DPORT EQU 0F0H ;DATA PORT CPORT EQU 0F1H ;CONTROL PORT SPORT EQU CPORT ;STATUS PORT BPORT EQU 0F2H ;BAUD RATE PORT ;RPORT EQU 69H ;RING INDICATOR PORT ; ;The following are CPORT commands ; RSTINS EQU 42H ;RESET USART AND SEND DTR MODINS1 EQU 4EH ;8 BITS, NO PARITY, 1 STOP BIT, 16X BAUD RATE MODINS2 EQU 0CEH ;8 BITS, NO PARITY, 2 STOP BITS, 16X BAUD RATE ONINS EQU 17H ;RESET ERROR FLAGS, SEND DTR, ENABLE RECEIVE ;AND TRANSMIT OFFINS EQU 10H ;DROP DTR, DISABLE RECEIVE AND TRANSMIT ; ;The following are SPORT status masks ; TRNRDY EQU 01H ;TRANSMITER EMPTY RCVRDY EQU 02H ;DATA AVAILABLE PERR EQU 08H ;PARITY ERROR ORERR EQU 10H ;OVERRUN ERROR FRERR EQU 20H ;FRAMING ERROR TOERR EQU ORERR + FRERR ;OVERRUN PLUS FRAMING ERROR DSR EQU 80H ;DATA SET READY ; ;The following are baud rates for BPORT. The lower 4 bits are used ; BD110 EQU 22H ;110 BAUD BD300 EQU 55H ;300 BAUD BD1200 EQU 77H ;1200 BAUD BD2400 EQU 0AAH ;2400 BAUD BD4800 EQU 0CCH ;4800 BAUD BD9600 EQU 0EEH ;9600 BAUD ; ;Ring indicator port mask ; RI EQU 40H ;NOT RING INDICATOR (LOW TRUE) P2RDET EQU RI ; ; ENDIF ;TREVORS ; ;--------------------------------------------------------- ; ORG 100H ; ;Move modem interface program up to high RAM and jump to it ;but first.. ; Ensure that the user is logged off if BYE is entered ; whilst the vectors have been PATCHED LD HL,(1) ;Get addr of jmp table in BIOS INC HL ;see if it points beyond this addr LD E,(HL) ; i.e., if it points above the BIOS INC HL ; it must have been patched LD D,(HL) ;addr now in DE LD HL,DEST ;get address of BYE code into HL LD A,L ; SUB HL,DE SUB E ; HL should be > DE LD L,A ; i.e., result should be >0 & <8 LD A,H SBC D ; MOV H,A AND 80H ;if result is negative (or >32k ) JP NZ,GOODBY ; CDOS is patched already ; MOVEUP LD BC,PEND-START+1 ;NUMBER OF BYTES TO MOVE LD HL,DEST+PEND-START+1;END OF MOVED CODE LD DE,SOURCE+PEND-START;END OF SOURCE CODE ; MVLP LD A,(DE) ;GET BYTE DEC HL ;BUMP POINTERS LD (HL),A ;NEW HOME DEC DE DEC BC ;BUMP BYTE COUNT LD A,B ;CHECK IF ZERO OR C JP NZ,MVLP ;IF NOT, DO SOME MORE ; PUSH HL ;SAVE FOR LATER JUMP LD A,0C3H ;CLEAR ANY TRAPS SO SYSOP.. LD (0),A ;CAN USER "BYE -A" XOR A ;NEXT WARMBOOT TO USR0/DRV A LD (4),A LD C,14 ;MAKE DRIVE A DEFAULT LD E,A ;LOG-IN DRIVE CP/M FUNCTION CALL BDOS ; RET ;TO ADRS PUSHED ABOVE ; ; SOURCE EQU $ ;BOUNDARY MEMORY MARKER ; OFFSET EQU DEST-SOURCE ;RELOC AMOUNT ; ;-----------------------------------------------; ; The following code gets moved ; ; to high 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 high XX ;XX RAM 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 ; XOR A ;GET 0 LD (LOSTFLG),A ;SHOW NO CARR. LOST ; ;Don't allow a remote user to do 'BYE -A' ; ;Check for -A option on command - request to ;go immediately into answer mode LD HL,FCB+1 ;TO OPTION LD A,(HL) CP '-' ;OPTION? JP NZ,HANGUP ;Should be JMP NOSLASH?? ;Got an option - validate it INC HL ;TO OPTION BYTE LD A,(HL) ;GET IT LD (OPTION),A ;MIGHT NEED LATER CP 'A' ;ANSWER? JP Z,ANSWER ; ;; IF COMFILE ;; CPI 'C' ;; JZ ANSWER ;; ENDIF ;COMFILE ; IF USRLOG ;CHECK FOR RESET OF COUNTERS CP 'R' CALL Z,RESET ENDIF ;USRLOG ; JP 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? JP C,HANGUP ;NOBODY THERE ; GOODBY EQU $+OFFSET CALL ILPRT ;PRINT THIS MSG: DEFB CR,LF,'Cheerio, please call again' DEFB CR,LF,0 CALL UNPATCH ;UNDO BIOS PATCHES ; ;Nobody there, or we are done, so hang up ; HANGUP EQU $+OFFSET LD SP,STACK ;SET UP LOCAL STACK XOR A ;FORCE NEXT WARMBOOT TO USER 0 LD (4),A ;AND DRIVE A LD C,14 ;MAKE DRIVE A DEFAULT LD E,A CALL BDOS LD A,' ' ;DON'T ALLOW OPTIONS.. LD (OPTION),A ;..AFTER 1 "BYE / " ; IF COMFILE CALL LODCOM ;LOAD THE COM FILE ENDIF ;COMFILE ; ; HANGUP2 EQU $+OFFSET ; ;Clear DTR causing phone to hang up ;Was some code in here I deleted by accident;;;;;;;;;;;;;;;; ;;OFFTI EQU $+OFFSET ;; CALL DELAY ;0.1 SECOND DELAY ;; DCR B ;; JNZ OFFTI ;KEEP LOOPING UNTIL FINISHED ;; POP B ;RESTORE B ;; MVI A,ONINS ;TURN DTR ON ALLOWING MODEM TO ANSWER PHONE ;; OUT CPORT ;; ENDIF ;SUPERB ; ; IF TREVORS ;code required ; ENDIF ;TREVORS ; LD A,0C3H ;CLEAR ANY TRAPS.. LD (0),A ;..LEFT FROM COM FILE ; ;Await ringing ; RINGWT EQU $+OFFSET ; ;Check local keyboard for CTL-C exit request. ;NOTE: Must do input via BDOS because CBIOS patches ;are not done until call comes in. ;; CALL UCSTS ;; ANI 7FH ;STRIP PARITY BIT ;; CPI 'C'-40H ;CONTROL C? ; ;; IF NOT USRLOG ;; JZ 0 ;YES, --EXIT-- TO CP/M ;; ENDIF ;NOT USRLOG ; ;; IF USRLOG ;PRINT OUT USER INFO ;; JZ PRNLOG ;; ENDIF ;USRLOG ; RINGW2 EQU $+OFFSET ;; IN RPORT ;GET THE STATUS ;; ANI P2RDET ;RINGING? ;; JNZ RINGWT ;NO, WAIT ; ;The phone may be ringing. Wait .1 sec and look ;again to make sure it isn't just relay bounce ;; CALL DELAY ;.1 SEC DELAY FOR DEBOUNCE ;; IN RPORT ;GET STATUS ;; ANI P2RDET ;STILL RINGING? ;; JNZ RINGWT ;NO, IT WAS RELAY BOUNCE ; ;The phone is definitely ringing, now wait until ring is finished ; ENDRING EQU $+OFFSET ;; CALL DELAY ;.1 SEC DELAY FOR DEBOUNCE ;; IN RPORT ;GET STATUS ;; ANI P2RDET ;STILL RINGING? ;; JZ ENDRING ;WAIT UNTIL RING FINISHED ; IF CALLBAK ;NEXT ROUTINES IMPLEMENT CALLBACK ; ;This routine minimizes the computer's interference ;with normal household phone use by having computer ;folk dial, let the phone ring once, hang up and ;then dial again. When the phone rings only once it ;alerts the computer which then waits for and answers ;any ring which occurs within the next 40 seconds. ; LD L,45 ;DELAY 4.5 SECONDS FOR NEXT RING ; WAITNX EQU $+OFFSET CALL DELAY ;WAIT .1 SECONDS DEC L ;MORE TO GO? JP NZ,WAITNX ;YES, LOOP IN A,RPORT ;GET THE STATUS AND P2RDET ;RINGING AGAIN? JP NZ,EXPECT ;NO?...ITS FOR ME! ; ;If second ring, then check for third ring, in case ;caller's phone exchange not synch'ed with computer's ; ENDRNG2 EQU $+OFFSET IN A,RPORT ;GET THE STATUS AND P2RDET ;STILL RINGING? JP Z,ENDRNG2 ;WAIT UNTIL RING FINISHED LD L,45 ;DELAY 4.5 SECONDS FOR NEXT RING ; WAITNX2 EQU $+OFFSET CALL DELAY ;WAIT .1 SECONDS DEC L ;MOE TO GO? JP NZ,WAITNX2 ;YES, LOOP IN A,RPORT ;GET THE STATUS AND P2RDET ;RINGING AGAIN? JP NZ,EXPECT ;NO?...ITS FOR ME! ; ;Call not for computer - wait until ringing done, then reset ; WAITNR EQU $+OFFSET LD L,100 ;WAIT FOR 10 SECS NO RINGING ; WAITNRL EQU $+OFFSET CALL DELAY ;DELAY .1 SECONDS IN A,RPORT ;GET THE STATUS AND P2RDET ;STILL RINGING? JP Z,WAITNR ;YES, WAIT 10 MORE SECONDS DEC L ;NO RING, MAYBE WE'RE DONE JP NZ,WAITNRL ;NO, LOOP SOME MORE ENDIF ;CALLBACK ; IF CALLBAK AND USRLOG LD A,(NONUSR) ;RECORD AS VOICE CALL INC A ;ADD ONE TO COUNT ENDIF ;CALLBAK AND USRLOG ; IF CALLBAK AND USRLOG AND DECIMAL DAA ;MAKE DECIMAL ENDIF ;CALLBK AND USRLOG AND DECIMAL ; IF CALLBAK AND USRLOG LD (NONUSR),A ;SAVE NEW COUNT ENDIF ;CALLBK AND USRLOG ; IF CALLBAK ;CONTINUE WITH CALLBAK ROUTINES JP HANGUP2 ;GO WAIT FOR NEXT CALL ; EXPECT EQU $+OFFSET LD HL,400 ;40 SECONDS TO WAIT FOR SECOND CALL ; RELOOK EQU $+OFFSET IN A,RPORT ;GET THE STATUS AND P2RDET ;RINGING AGAIN? JP Z,ANSWER ;YES, GO ANSWER IT CALL DELAY ;WAIT .1 SECOND DEC HL ;ONE LESS COUNT LD A,H OR L ;IS COUNT ZERO? JP NZ,RELOOK ;NO, LOOK SOME MORE JP HANGUP2 ;COUNT DONE, WAIT FOR NEW CALL ; ENDIF ;END OF CALLBACK ROUTINES ; ;Setup modem ; ANSWER EQU $+OFFSET ; IF USRLOG ;COUNT # OF LOGON ATTEMPTS LD A,(OLDUSR) ;GET # OF ATTEPMTS INC A ;ADD THIS CALL ENDIF ;USRLOG ; IF USRLOG AND DECIMAL DAA ;MAKE IT DECIMAL ENDIF ;USRLOG AND DECIMAL ; IF USRLOG LD (OLDUSR),A ;SAVE NEW COUNT ENDIF ;USRLOG ;----------------------------------------------------- IF TREVORS LD A,BD300 ;LOAD 300 BAUD OUT BPORT,A LD A,2 ;ensure UART points at cmd register OUT CPORT,A CALL UDELAY OUT CPORT,A CALL UDELAY OUT CPORT,A CALL UDELAY LD A,RSTINS ;RESET USART OUT CPORT,A CALL UDELAY ;USART DELAY LD A,MODINS2 ;2 STOP BITS, ETC. OUT CPORT,A CALL UDELAY ;USART DELAY LD A,ONINS ;DSR, ETC. OUT CPORT,A CALL CARCK ;SEE IF CARRIER IS PRESENT JP C,HANGUP2 ;Test input for baud rate IN A,DPORT ;Clear any rubbish IN A,DPORT CALL PATCH ;PATCH JUMP TABLE CALL TSTBAUD ;SEE IF 300 BAUD JP Z,WELCOME ;YES, EXIT ; LD A,BD1200 ;LOAD 1200 BAUD OUT BPORT,A CALL TSTBAUD ;SEE IF 1200 BAUD JP Z,WELCOME ;YES,EXIT ; LD A,BD110 ;LOAD 110 BAUD OUT BPORT,A CALL TSTBAUD ;TEST FOR 110 BAUD JP Z,WELCOME ENDIF ;TREVORS ; ;;; CALL UNPATCH JP ANSWER ;TEST MORE - INVALID BAUD RATE ; IF TREVORS UDELAY EQU $+OFFSET NOP NOP NOP NOP NOP NOP RET ENDIF ;TREVORS ; ;Get the console status when unpatched ; UCSTS EQU $+OFFSET ; LD C,CSTS ;IN CPM 1.4, WE HAVE TO GET.. CALL BDOS ;..THE STATUS FIRST OR A RET Z LD C,CI ;AND THEN THE CHARACTER CALL BDOS RET ; ;Following are the USRLOG routines ; IF USRLOG ;INCLUDE RESET FUNCTIONS RESET EQU $+OFFSET ;RESET ALL LOGON COUNTERS XOR A ENDIF ;USRLOG ; IF USRLOG AND PWRQD LD (OLDUSR),A ;RESET ATTEMPT COUNTER ENDIF ;USRLOG AND PWRQD ; IF USRLOG LD (NEWUSR),A ;RESET LOGON COUNTER ENDIF ;USRLOG ; IF USRLOG AND CALLBAK LD (NONUSR),A ;RESET VOICE COUNTER ENDIF ;USRLOG AND CALLBAK ; IF USRLOG RET ENDIF ;USRLOG ; PRNLOG EQU $+OFFSET ; IF USRLOG AND PWRQD;PRINT # OF LOGON ATTEMPTS LD C,PRINTF LD DE,ATMSG CALL BDOS LD A,(OLDUSR) CALL HXOUT ENDIF ;USRLOG AND PWRQD ; IF USRLOG ;PRINT # OF LOGONS LD C,PRINTF LD DE,SUMSG CALL BDOS LD A,(NEWUSR) CALL HXOUT ENDIF ;USRLOG ; IF USRLOG AND CALLBAK;# OF VOICE CALLS LD C,PRINTF LD DE,VCMSG CALL BDOS LD A,(NONUSR) CALL HXOUT ENDIF ;USRLOG AND CALLBAK ; IF USRLOG JP 0 ;WARM-BOOT BACK TO CP/M ENDIF ;USRLOG ; IF USRLOG AND PWRQD ATMSG EQU $+OFFSET DEFB LF,CR,'NUMBER OF LOGON ATTEMPTS: $' ENDIF ;USRLOG AND PWRQD ; IF USRLOG SUMSG EQU $+OFFSET DEFB LF,CR,'NUMBER OF LOGONS: $' ENDIF ;USRLOG ; IF USRLOG AND CALLBAK VCMSG EQU $+OFFSET DEFB LF,CR,'NUMBER OF VOICE CALLS: $' ENDIF ;USRLOG AND CALLBAK ; IF USRLOG HXOUT EQU $+OFFSET LD B,A ;SAVE NUMBER RRA ;ROTATE RIGHT 4 BITS RRA ;TO MAKE AN ASCII DIGIT RRA RRA CALL ONEOUT ;OUTPUT MSH TO CONSOLE LD A,B ;GET NUMBER BACK ; ONEOUT EQU $+OFFSET AND 0FH ;GET LSH FOR OUTPUT CP 0AH ;CHECK IF ALPHA JP C,NOTAL2 ADD 07H ; NOTAL2 EQU $+OFFSET ADD 30H PUSH BC LD C,02H LD E,A ;OUTPUT THE NUMBER CALL BDOS POP BC RET ENDIF ;USRLOG ; ;Welcome to the system ; WELCOME EQU $+OFFSET ; GETNULL EQU $+OFFSET CALL ILPRT ;PRINT THIS MSG: DEFB CR,LF DEFB 'HOW MANY NULLS (0-9) DO YOU NEED? ',0 CALL MINPUT ;GET VALUE ;;; MOV C,A ;TO C FOR MOUTPUT CALL MOUTPUT ;ECHO CHAR ;;; MOV A,C ;RESTORE VALUE CP '0' JP C,GETNULL ;BAD, RETRY CP '9'+1 JP NC,GETNULL ;BAD SUB '0' ;MAKE BINARY LD (NULLS),A ;SAVE COUNT ; IF TRAPLC GETULC EQU $+OFFSET CALL ILPRT ;PRINT THIS MSG: DEFB CR,LF DEFB 'CAN YOUR TERMINAL DISPLAY LOWER CASE? ',0 LD A,20H ;FORCE CASE CONVERSION FOR NOW LD (ULCSW),A CALL MINPUT ;GET Y OR NO ;;; MOV C,A CALL MOUTPUT ;ECHO ;;; MOV A,C CP 'N' JP Z,DONEOPT ;WE'RE ALREADY SET UP FOR NO LWR CASE CP 'Y' JP NZ,GETULC ;WASN'T Y OR N...GO ASK AGAIN XOR A LD (ULCSW),A ;SET FLAG FOR NO CONVERSION ; DONEOPT EQU $+OFFSET ENDIF ;TRAPLC ; CALL ILPRT DEFB CR,LF,0 ;Print the welcome file LD HL,WELFILN ;SOURCE LD DE,FCB ;DESTINATION LD B,13 ;LENGTH CALL MOVE ;MOVE THE NAME ;Set DMA address to 80h LD DE,80H LD C,STDMA CALL BDOS ; ;Open the welcome file LD DE,FCB LD C,OPEN CALL BDOS ;Did it exist? INC A ;A=> 0 MEANS "NO" JP Z,PASSINT ;NO WELCOME FILE ;Got a file, type it XOR A ;GET 0 LD (FCBRNO),A ;ZERO RECORD # LD HL,100H ;GET INITIAL BUFF POINTER ; ;Type the welcome file WELTYLP EQU $+OFFSET CALL RDBYTE ;GET A BYTE CP 1AH ;EOF? JP Z,PASSINT ;YES, DONE ;;; MOV C,A ;SETUP FOR TYPE CALL MOUTPUT ;TYPE THE CHAR CALL MSTAT ;CHECK FOR.. OR A ;CHAR TYPED? JP Z,WELTYLP ;..NO, LOOP CALL MINPUT ;..YES, GET CHAR CP 'C'-40H ;CTL-C? JP NZ,WELTYLP ;..NO, LOOP UNTIL EOF ; ;Get the password ; PASSINT EQU $+OFFSET ; IF PWRQD LD D,5 ;5 TRIES AT PASSWORD ; PASSINP EQU $+OFFSET CALL ILPRT DEFB CR,LF,'ENTER PASSWORD: ',0 LD HL,PASSWD ;POINT TO PASSWORD LD E,0 ;NO MISSED LETTERS IN A,DPORT ;CLEAR OUT GARBAGE ; PWMLP EQU $+OFFSET CALL MINPUT ;GET A CHAR CP 'U'-40H ;CTL-U? JP Z,PASSINP ;YES, RE-GET IT CP 60H ;LOWER CASE? JP C,NOTLC ;NO, AND 5FH ;MAKE UPPER CASE ALPHA ; NOTLC EQU $+OFFSET CP (HL) ;MATCH PASSWORD? JP Z,PWMAT ;..YES LD E,1 ;..NO, SHOW MISS CP CR ;C/R? JP NZ,PWMLP ;..NO, WAIT FOR C/R ; ;Password didn't match ; PWNMAT EQU $+OFFSET CALL ILPRT DEFB '++INCORRECT++',CR,LF,0 DEC D ;MORE TRIES? JP NZ,PASSINP ;YES JP BADPASS ;NO, GO HANG UP ; ;Character matched in password ; PWMAT EQU $+OFFSET INC HL ;TO NEXT CHAR CP CR ;END? JP NZ,PWMLP ;..NO, LOOP ;End of password. Any missed chars? LD A,E ;GET FLAG OR A JP NZ,PWNMAT ;NOT RIGHT ;Password correct ENDIF ;PWRQD ; NOPASS EQU $+OFFSET ; IF USRLOG ;COUNT # OF SUCCESSFUL LOGONS LD A,(NEWUSR) ;GET LAST VALUE INC A ;INCREMENT IT ENDIF ;USRLOG ; IF USRLOG AND DECIMAL DAA ;MAKE IT DECIMAL ENDIF ;USRLOG AND DECIMAL ; IF USRLOG LD (NEWUSR),A ;SAVE NEW VALUE ENDIF ;USRLOG ; ;; CALL ILPRT ;; DB CR,LF,'Booting CDOS.. ',0DH,0AH,0 ;PUT BOOT-UP MSG HERE ; IF COMFILE LD A,(OPTION) CP 'A' ;SYSOP CAN BYPASS COM FILE BY.. JP Z,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 LD A,'@' ;Tell RBBS that this is a LD (5DH),A ; new caller JP 100H ;EVERYONE ELSE GETS COM FILE ENDIF ;COMFILE ; IF NOT COMFILE JP 0 ENDIF ;NOT COMFILE ; ;TSTBAUD attempts to read a LF or CR, returns with ;zero flag if the character read is one of these two. ; TSTBAUD EQU $+OFFSET CALL MINPUT ;GET CHARACTER FROM MODEM CP CR ;IF A CARRIAGE RETURN... RET Z ;.. RETURN CP LF ;IF A LINEFEED... RET ;RET ZERO FLAG, ELSE NOT ZERO ; ;Loss of connection test ; CARCK EQU $+OFFSET ; ;;; IF SUPERB ; ;Racal-Vadic modem automatically hangs up phone 1 second ;after carrier loss. ; ;;; IN SPORT ;GET STATUS ;;; ANI DSR ;CHECK IF CARRIER ON ;;; JNZ CARCK2 ;YES, CONTINUE ON ;;; STC ;SET CARRY BIT FOR NO CARRIER ;;; RET ;;; ENDIF ;SUPERB ; IF TREVORS ; ;; IN SPORT ;GET STATUS ;; ANI DSR ;CHECK IF CARRIER ON ;; JNZ CARCK2 ;YES, CONTINUE ON ;******************always have carrier ;; STC ;SET CARRY BIT FOR NO CARRIER ;; RET ENDIF ;TREVORS ; ;Now test drive #'s and (if CP/M 2.x) user #'s to ;insure that maximums are not exceeded. ; CARCK2 EQU $+OFFSET LD A,(4) ;CHECK DISK/USER # AND 0FH ;ISOLATE DRIVE CP MAXDRV ;VALID DRIVE? JP C,CARCK3 ;YES, SKIP THIS JUNK LD A,(4) ;GET WHOLE LOGIN BYTE AND 0F0H ;RETAIN USER # & FORCE DRIVE TO A LD (4),A ;UPDATE LOGIN BYTE CALL ILPRT ;TELL USER WHAT HE DID DEFB 'Invalid drive - returning to A:',0 JP 0 ;WARM BOOT ; CARCK3 EQU $+OFFSET ; CARCK4 EQU $+OFFSET OR A RET ; ;.1 sec delay routine ; DELAY EQU $+OFFSET ;; PUSH B ; ;; IF FASTCLK ;; LXI B,16667 ;4 MHZ TIMING CONSTANT ;; ENDIF ; ;; IF NOT FASTCLK ;; LXI B,8334 ;2 MHZ TIMING CONSTANT ;; ENDIF ; ;;DELAY1 EQU $+OFFSET ;; DCX B ;; MOV A,B ;; ORA C ;; JNZ DELAY1 ;; POP B ;; RET ; ;50 ms delay routine ; ;;KDELAY EQU $+OFFSET ;; PUSH B ; ;; IF FASTCLK ;; LXI B,8334 ;; ENDIF ; ;; IF NOT FASTCLK ;; LXI B,4167 ;; ENDIF ; ;; JMP DELAY1 ; ;Patch in the new JMP table (saving the old) ; PATCH EQU $+OFFSET CALL TBLADDR ;CALC HL= CP/M JMP TABLE LD DE,VCOLDBT ;POINT TO SAVE LOCATION LD 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 EX DE,HL ;MOVE TO DE LD HL,NEWJTBL ;POINT TO NEW CALL MOVE ;MOVE IT ; IF CDOS ;we must copy and replace SDVT console entries ; LD C,81H CALL BDOS ;Get user register pointer LD HL,3 ADD HL,BC ;HL now pointing to SDVT entry LD E,(HL) INC HL LD D,(HL) ;Have SDVT vector in DE EX DE,HL ;in HL LD E,(HL) INC HL LD D,(HL) ;Have CON$TABLE in DE EX DE,HL ;in HL LD (CON$TABLE),HL ;save it in RAM LD DE,DOSSDVT ;where we will save it LD B,10 ;10 bytes to move CALL MOVE ;(hl) to (de) ; LD HL,(CON$TABLE) ;Now overlay with our SDVT EX DE,HL LD HL,SDVT ;our SDVT points to modem routines LD B,10 CALL MOVE ; ; Now patch the vectors into our CONIN etc LD HL,(DOSCSTAT) LD (CSTAT),HL LD HL,(DOSCIND) LD (CIND),HL LD HL,(DOSCOUTD) LD (COUTD),HL IF NOT PRINTER ; Now replace printer table LINIT and LOUT entry LD C,81H CALL BDOS ;Get user register pointer LD HL,3 ;calculate the SDVT entry ADD HL,BC LD E,(HL) INC HL LD D,(HL) ;Have SDVT table addr in DE LD HL,8 ;get LIST table addr ADD HL,DE LD E,(HL) INC HL LD D,(HL) ;DE points at LIST table INC DE INC DE EX DE,HL LD (LRDY$ADDR),HL ;where we will save it LD E,(HL) INC HL LD D,(HL) ;Have original LRDY vector in DE EX DE,HL ;inHL LD (SAVE$LRDY),HL EX DE,HL ;get back table ptr INC HL LD E,(HL) INC HL LD D,(HL) ;have LOUT vec in DE EX DE,HL LD (SAVE$LOUT),HL CALL DISABLE$PRINTER ENDIF ;NOT PRINTER ENDIF ;CDOS RET ; ;Now replace the vectors if required IF NOT PRINTER ;we will patch out table entries DISABLE$PRINTER EQU $+OFFSET LD HL,(LRDY$ADDR) LD DE,MSTAT1 ;Replace vector LD (HL),E INC HL LD (HL),D ; INC HL ;now replace LOUT LD DE,DUMMY ;merely RETurn LD (HL),E INC HL LD (HL),D RET ; ENABLE$PRINTER EQU $+OFFSET ;Now return the vectors if required LD HL,(SAVE$LRDY) ;get original vector EX DE,HL ;into DE LD HL,(LRDY$ADDR) LD (HL),E INC HL LD (HL),D ; INC HL ;now replace LOUT PUSH HL LD HL,(SAVE$LOUT) EX DE,HL POP HL LD (HL),E INC HL LD (HL),D RET ENDIF ;NOT PRINTER UNPATCH EQU $+OFFSET CALL TBLADDR ;HL=CP/M'S JMP TABLE EX DE,HL ;MOVE TO DE LD HL,VCOLDBT ;GET SAVED TABLE CALL MOVE ;MOVE ORIG BACK ; IF CDOS ;must also move SDVT back LD HL,(CON$TABLE) EX DE,HL ;DE now holds addr of CDOS's SDVT LD HL,DOSSDVT ;HL has the saved SDVT addr LD B,10 ;length of SDVT CALL MOVE ;restore old SDVT IF NOT PRINTER CALL ENABLE$PRINTER ENDIF ;NOT PRINTER ENDIF ;CDOS RET ; ;Calculate HL=CP/M's jump table, B=length ; TBLADDR EQU $+OFFSET LD HL,(1) ;GET BIOS POINTER DEC HL ;..SKIP DEC HL ;..TO DEC HL ;..COLD BOOT ; IF NOT CDOS IF NOT PRINTER LD B,18 ;BYTES TO MOVE ENDIF ; IF PRINTER ;RETAIN LIST DEVICE? LD B,15 ;DON'T MOVE LISTER JUMP ENDIF ; ENDIF ;NOT CDOS IF CDOS LD B,6 ;only copy the two boot vectors ENDIF ;CDOS RET ; ;Move (HL) to (DE), length in (B) ; MOVE EQU $+OFFSET LD A,(HL) ;GET A BYTE LD (DE),A ;PUT AT NEW HOME INC DE ;BUMP POINTERS INC HL DEC B ;DEC BYTE COUNT JP NZ,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 RET NC ;ALL OK ; ;Carrier is lost. Type message so local console shows the reason ; BADPASS EQU $+OFFSET ;COME HERE ON BAD PASSWORD LD A,1 ;SHOW CARRIER LOST SO LD (LOSTFLG),A ;..WE WON'T CK AGAIN LD SP,STACK ;ENSURE VALID STACK CALL ILPRT DEFB CR,LF DEFB '++CARRIER LOST++' DEFB CR,LF,' ',0 CALL UNPATCH ;RESTORE ORIG BIOS JMP TBL XOR A ;CLEAR OUT CARRIER.. LD (LOSTFLG),A ;..LOST FLAG JP HANGUP ; ;Readbyte routine - used to read the welcome file ; RDBYTE EQU $+OFFSET LD A,H ;TIME TO READ? OR A ;..IF AT 100H JP Z,NORD ;NO READ REQ'D ;Have to read a sector LD DE,FCB LD C,READ CALL BDOS OR A ;OK? LD A,1AH ;FAKE UP EOF RET NZ ;RET EOF IF BAD LD HL,80H ; NORD EQU $+OFFSET LD A,(HL) ;GET CHAR INC HL ;TO NEXT RET ; ;Keyboard/modem status test routine ; MSTAT EQU $+OFFSET ; IF DUAL$IO ;WANT LOCAL CONSOLE? CALL CONSTAT ;GET LOCAL STATUS OR A RET NZ ;RET IF LOCAL CHAR ENDIF ;DUAL$IO ; IF TREVORS IN A,SPORT ;GET STATUS AND RCVRDY ;GOT A CHARACTER RET Z ;RETURN IF NOT ;; IN SPORT ;GET STATUS ;; ANI TOERR ;CHECK FOR FRAMING AND OVERRUN ERRORS ;; JZ MSTAT1 ;NO ERRORS ;; MVI A,ONINS ;RESET ERROR FLAGS ;; OUT CPORT ;; XRA A ;RETURN FALSE ;; RET ENDIF ;TREVORS ; MSTAT1 EQU $+OFFSET LD A,0FFH ;SHOW READY OR A RET ; ;Modem input function, checks local console first ; MINPUT EQU $+OFFSET ; IF TIMEOUT PUSH HL LD HL,TOVALUE*MINUTES;INITIALIZE TIMEOUT COUNTER LD (TOCNT),HL POP HL ENDIF ;TIMEOUT ; MINPUT1 EQU $+OFFSET LD A,(LOSTFLG) ;KNOWN LOSS.. OR A ;..OF CARRIER? CALL Z,CHECK ;CARRIER STILL ON? CALL MSTAT ;ANYTHING? OR A ; IF NOT TIMEOUT JP Z,MINPUT ;LOOP TILL CHAR RCD ENDIF ;NOT TIMEOUT ; IF TIMEOUT JP NZ,MINPUT2 CALL KDELAY ;KILL 50 MS PUSH HL LD HL,(TOCNT) ;KNOCK DOWN TIMEOUT COUNTER DEC HL LD (TOCNT),HL LD A,H OR L POP HL JP NZ,MINPUT1 ;STILL TIME LEFT..KEEP TRYING CALL ILPRT DEFB '++INPUT TIMED OUT++',7,7,0 JP NOSLASH ENDIF ;TIMEOUT ; MINPUT2 EQU $+OFFSET ; IF DUAL$IO ;BOTH LOCAL AND REMOTE CALL CONSTAT ;CHECK LOCAL CONSOLE OR A ;CHAR? JP NZ,CONIN ;..YES, READ IT, RET. ENDIF ; ;Local console wasn't ready, so read modem ; IN A,DPORT ;GET DATA BYTE AND 7FH ;DELETE PARITY JP Z,MINPUT ;IGNORE NULLS ; IF HARDLOG CP 20H JP NC,MINPUT3 CP CR JP NZ,NOLOG ; MINPUT3 EQU $+OFFSET CALL LISTOUT ;ECHO ON PRINTER CP CR JP NZ,NOLOG ;CR NEEDS LINEFEED LD A,LF CALL LISTOUT ;SO SEND IT LD A,CR ;GET BACK CR ENDIF ;END OF HARDLOG ; NOLOG EQU $+OFFSET ; CP 3 ;IS IT CONTROL-C? RET NZ ;NO, PASS IT THRU LD A,(0) ;SEE IF WARM BOOT DISABLED CP 0C3H ;JMP MEANS WARM BOOT OK LD A,3 ;SO RETURN CONTROL-C RET Z XOR A ;ELSE CONVERT TO NULL RET ; ;Modem output function ; MOUTPUT EQU $+OFFSET LD C,A ;char is passed in A for CDOS CMOUTPUT EQU $+OFFSET ;CP/M passes it in C ; ;If we already know carrier is lost, don't check ;for it again or loop trying to output. LD A,(LOSTFLG) ;KNOWN LOSS OF CARRIER? OR A JP NZ,SILENT ;AVOID LOOP IN CASE CARRIER LOST CALL CHECK ;CARRIER STILL ON? ; IF TREVORS IN A,SPORT ;GET MODEM STATUS AND TRNRDY ;TRANSMIT BUFFER EMPTY? ENDIF ;TREVORS ; JP Z,CMOUTPUT ;LOOP IF NOT READY ; LD A,C ;GET CHAR AND 7FH ;STRIP PARITY BIT ; IF TRAPLC CP 60H ;CHECK FOR LOWER CASE JP C,MOUTP2 ;SKIP IF NOT LC CP 7FH ;CHECK FOR RUBOUT JP Z,MOUTP2 PUSH HL LD HL,ULCSW ;SUBTRACT EITHER 20H OR 0 SUB (HL) POP HL LD C,A ;FORCE ON LOCAL AS WELL AS REMOTE ; MOUTP2 EQU $+OFFSET ENDIF ;TRAPLC ; OUT DPORT,A ;OUTPUT TO MODEM ; SILENT EQU $+OFFSET ; IF DUAL$IO ;TO LOCAL ALSO? LD A,C ;for CDOS PUSH AF ;SAVE CHAR CALL CONOUT ;SEND TO REGULAR BIOS char in A or C POP AF ;GET CHAR AGAIN ENDIF ;DUAL$IO ; ;Check for nulls CP LF ;TIME FOR NULLS? RET NZ ;NO, RETURN ;Send nulls if required LD A,(NULLS) ;GET COUNT OR A ;ANY? RET Z ;..NO PUSH BC LD B,A ;SAVE COUNT LD A,0 ;0 IS A NULL ; NULLP EQU $+OFFSET CALL MOUTPUT ;TYPE A NULL DEC B ;MORE? JP NZ,NULLP ;..YES, LOOP POP BC LD C,LF ;RESTORE LF 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 JP VWARMBT ;++++++++++++++;;;;;;;;;;;;;;;;;;;;;;;; ; ;Inline print routine ; ILPRT EQU $+OFFSET EX (SP),HL ;SAVE HL, GET MSG PUSH BC ;SAVE BC REGS ; ILPLP EQU $+OFFSET LD C,(HL) ;GET CHAR CALL CMOUTPUT ;OUTPUT IT INC HL ;POINT TO NEXT LD A,(HL) ;TEST OR A ;..FOR END JP NZ,ILPLP POP BC ;RESTORE BC REGS EX (SP),HL ;RESTORE HL, RET ADDR RET ;RET PAST MSG ; IF PWRQD ;KEEP PASSWORD HERE ;Access password (ends in carriage return) ; PASSWD EQU $+OFFSET DEFB 'HELLO' ;THE PASSWORD ITSELF DEFB CR ;END OF PASSWORD ;Allow room for bigger password to be patched in DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0 ENDIF ;PWRQD ; ;Routine to load the COM file ; IF COMFILE LODCOM EQU $+OFFSET XOR A ;INITIALIZE FCB LD (COMFCB),A LD HL,COMFCB+12 LD B,21 ; ZLOOP EQU $+OFFSET LD (HL),0 INC HL DEC B JP NZ,ZLOOP ; LD C,OPEN ;NOW OPEN THE FILE LD DE,COMFCB CALL BDOS INC A ;SHOULD BE NON-ZERO JP Z,ABORT ;NO FILE, ABORT ; ;Now load the file LD HL,(6) ;GET TOP OF MEMORY LD DE,-80H ;RECORD LOADS CAN'T START.. ADD HL,DE ;..ABOVE (BDOS) - 80H PUSH HL ;SAVE ON STACK ; LD DE,80H ;TPA-80H LD BC,0 ;KEEP A RECORD COUNTER PUSH BC ;SAVE COUNTER PUSH DE ;AND LOAD ADDRESS ; GLOOP EQU $+OFFSET POP DE ;GET TPA ADRS LD HL,80H ;POINT TO NXT ADRS TO READ TO ADD HL,DE ;HL HAS THE ADDRESS POP BC ;INCREMENT THE COUNTER ;Check for load past top-of-memory POP DE ;GET (TOP-OF-MEMORY) PUSH DE ;RE-SAVE FOR NEXT TIME LD A,E ;SUBTRACT: (TOP) - (ADRS) SUB L LD A,D ;ONLY THE CARRY NEEDED SBC H JP NC,SIZEOK ;CY= BETTER MOVCPM CALL ERRXIT ;SO TELL THE STORY DEFB 'Out of memory','$' ; SIZEOK EQU $+OFFSET INC BC PUSH BC PUSH HL ;SAVE TPA ADRS EX DE,HL ;ALIGN REGISTERS LD C,STDMA ;TELL BDOS WHERE TO PUT RECORD CALL BDOS LD DE,COMFCB ;NOW READ THE RECORD LD C,READ CALL BDOS OR A JP Z,GLOOP ;A=0 IF MORE TO READ POP BC ;UNJUNK STACK POP BC ;THIS IS OUR COUNTER POP HL ;MORE JUNK ON STACK LD A,B ;CHECK FOR ZERO OR C JP Z,ABORT ;WE SHOULD HAVE READ SOMETHING LD DE,80H ;WE DID, RESET DMA TO 80H LD C,STDMA CALL BDOS CALL LOADOK ;PRINT THIS MSG TO CONSOLE: DEFB 'RBBS loaded',CR,LF,'$' ; LOADOK EQU $+OFFSET POP DE LD A,(OPTION) ;SEE IF THIS WAS "BYE /C" CP 'C' ;IF IT WAS THEN.. RET Z ;..DON'T PRINT MESSAGE LD C,PRINTF CALL BDOS RET ; ABORT EQU $+OFFSET CALL ERRXIT DEFB CR,LF DEFB 'Open err','$' ; ERRXIT EQU $+OFFSET POP DE LD C,PRINTF CALL BDOS ;PRINT THE ABORT MSG JP 0 ;WARM BOOT 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 BC PUSH DE PUSH HL CSTAT EQU $+1+OFFSET CALL VCONSTAT POP HL POP DE POP BC RET ; CONIN EQU $+OFFSET PUSH BC PUSH DE PUSH HL CIND EQU $+1+OFFSET CALL VCONIN ; IF FKEYS CALL CKFUNC ENDIF ;FKEYS ; POP HL POP DE POP BC RET ; CKFUNC EQU $+OFFSET ; IF FKEYS CP SYSDKEY JP Z,SYSDOWN ;TELL CALLER TO LEAVE CP TWITKEY JP Z,GOODBY ;MAKE CALLER LEAVE ;; CP MSGKEY ;; RET NZ ;; CALL ILPRT ;SEND CALLER A MESSAGE ;; DEFB 'MESSAGE FROM OPERATOR:',0 ;; LD A,' ' ;SOMETHING TO RETURN WITH RET ; SYSDOWN EQU $+OFFSET CALL ILPRT DEFB 'SYSTEM DOWN IN' DEFB ' 5 MINUTES....',0 LD A,' ' RET ENDIF ;FKEYS ; CONOUT EQU $+OFFSET PUSH BC PUSH DE PUSH HL ; MOV A,C ;Get char in A for CDOS PUSH AF COUTD EQU $+1+OFFSET CALL VCONOUT POP AF POP HL POP DE POP BC RET ; LISTOUT EQU $+OFFSET PUSH BC PUSH DE PUSH HL PUSH AF IF NOT PRINTER CALL ENABLE$PRINTER ENDIF ;NOT PRINTER POP AF PUSH AF LD A,C ;char needed in A LOUT EQU $+1+OFFSET CALL VLISTOUT IF NOT PRINTER CALL DISABLE$PRINTER ENDIF ;NOT PRINTER POP AF POP HL POP DE POP BC MINIT EQU $+OFFSET ;merely a return opcode RET ; ;This is the JMP table which is copied on top ;of the one pointed to by location 1 in CP/M ;If CDOS is in use only the first 2 vectors are replaced NEWJTBL EQU $+OFFSET JP MBOOT ;COLD BOOT JP MBOOT ;WARM BOOT JP MSTAT ;MODEM STATUS TEST JP MINPUT ;MODEM INPUT ROUTINE JP CMOUTPUT ;MODEM OUTPUT ROUTINE DUMMY EQU $+OFFSET RET ;DUMMY LIST DEVICE NOP NOP ; WELFILN EQU $+OFFSET DEFB 0,'WELCOME ',0 ;Welcome file name ^^^^^^^^^^^ (must be 11 characters) ; NULLS EQU $+OFFSET DEFB 5 ; COMFCB EQU $+OFFSET DEFB 0,'RBBS COM' ;COM file name ^^^^^^^^^^^ (must be 11 characters) ; IF NOT CDOS PEND EQU $+OFFSET ;END OF RELOCATED CODE ENDIF ;NOT CDOS ; ;These areas are not initialized for CP/M only ; DEFS 21 ;REST OF COM FCB ; IF CDOS ; This is the SDVT table which is copied on top ; of the one in CDOS or IOS SDVT EQU $+OFFSET ;10 BYTES LONG DEFW MINIT ;returns OK immediately DEFW MSTAT DEFW MINPUT DEFW MSTAT1 ;wants status,gets READY DEFW MOUTPUT ; PEND EQU $+OFFSET ;END OF RELOCATED CODE ; DEFS 2 ;to allow for movement errors CON$TABLE EQU $+OFFSET DEFS 2 ;Store DOSSDVT addr here LRDY$ADDR EQU $+OFFSET DEFS 2 SAVE$LRDY EQU $+OFFSET DEFS 2 SAVE$LOUT EQU $+OFFSET DEFS 2 ; ;Save the original SDVT here DOSSDVT EQU $+OFFSET DEFS 2 DOSCSTAT EQU $+OFFSET DEFS 2 DOSCIND EQU $+OFFSET DEFS 2 DEFS 2 DOSCOUTD EQU $+OFFSET DEFS 2 ; ENDIF ;CDOS ULCSW EQU $+OFFSET DEFS 1 ; OPTION EQU $+OFFSET DEFS 1 ; TOCNT EQU $+OFFSET DEFS 2 ; ;Byte to keep track of lost carrier when ;typing "++CARRIER LOST++" so we don't loop ; LOSTFLG EQU $+OFFSET DEFS 1 ; ;Save the CP/M jump table here ; VCOLDBT EQU $+OFFSET DEFS 3 ; VWARMBT EQU $+OFFSET DEFS 3 ; VCONSTAT EQU $+OFFSET DEFS 3 ; VCONIN EQU $+OFFSET DEFS 3 ; VCONOUT EQU $+OFFSET DEFS 3 ; VLISTOUT EQU $+OFFSET DEFS 3 ; ;Since these areas are not initialized, ;the following counters will not be changed ;by subsequent loads of this program ; IF USRLOG OLDUSR EQU $+OFFSET DEFS 1 ; NEWUSR EQU $+OFFSET DEFS 1 ; NONUSR EQU $+OFFSET DEFS 1 ENDIF ;USRLOG ; ; DEFS 60 STACK EQU $+OFFSET ;LOCAL STACK ; ENDMARK EQU $+OFFSET IGNORE ERROR. THIS MARKS END OF PGM ; ;BDOS equates ; CI EQU 1 WRCON EQU 2 DRECTIO EQU 6 PRINTF EQU 9 CSTS EQU 11 OPEN EQU 15 READ EQU 20 STDMA EQU 26 BDOS EQU 5 FCB EQU 5CH FCBRNO EQU FCB+32 ; END