home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol007
/
dchbye55.asm
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
23KB
|
988 lines
;V5.5 (Revised 9/12/80)
;
;
;REMOTE CONSOLE PROGRAM FOR CP/M
;BASED ON AN ORIGINAL PROGRAM WRITTEN
;BY DAVE JAFFE, JANUARY 1979
;
;Rewritten for PMMI modem
;by Ward Christensen, February 1979
;
;Lobotomized for D C Hayes 80-103
;by Bruce Ratoff, May 1980
;
;
;I'd also like to give credit to Bill Precht
; for the "label + offset" idea allowing
; this program to relocate itself
; without using DDT to initially set it up
;
;05/06/79 Added routine to allow "callback" operation so modem
; does not answer normal voice calls. By Robbin Hough
; and Keith Petersen, W8SDZ.
;
;09/24/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.
;
;01/24/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.
;
;05/12/80 Changed modem I/O equates, ports and flags for the
; D C Hayes 80-103A.
; By Bruce Ratoff
;
;05/20/80 Put test at CARCK to force valid user/drive, as
; suggested by Keith Petersen.
; by Bruce Ratoff
;
;05/26/80 Put in "warm boot command" logic to force user into
; a chosen CCP command and disable warm boot on entry.
; The JMP at location 0 is replaced by a CALL, which
; is used to tell BYE to disconnect instead of doing
; warm boot. Program may re-enable warm boot by storing
; JMP opcode back into location 0. Also, whenever
; warm boot is disabled, control-c is converted to null.
; by Bruce Ratoff
;
;06/04/80 Added keyboard input timeout to eliminate the "asleep
; at the switch" phenomenon and telco noises that sound
; like a carrier.
; by Bruce Ratoff
;
;06/08/80 Added (optional) lower-to-upper case conversion on output
; by asking extra question at signon.
; by Bruce Ratoff
;
;06/11/80 Ignore modem characters received with framing or overrun
; errors. This should help eliminate some of the noise
; sensitivities.
; by Bruce Ratoff
;
;09/12/80 Reset user 0/drive A in move-up logic so BYE /A works
; from other drives/users.
; by Bruce Ratoff
;
;------------------------------------------------
;CHANGE THE FOLLOWING EQUATE TO AN AREA IN YOUR
;HI MEMORY WHERE THIS PROGRAM MAY PATCH ITSELF IN.
;APPROX MEMORY REQUIREMENTS: 900 BYTES.
;
DEST EQU 0F800H ;RUNNING LOCATION OF CODE
;
;CHANGE THE FOLLOWING TO YOUR LOCAL CONSOLE KEYBOARD
;DATA PORT NUMBER.
;
CONDATA EQU 05H ;LOCAL CONSOLE INPUT DATA PORT
;
;CHANGE THE FOLLOWING IF YOUR HAYES IS NOT AT 090H
;(THE OTHER PORT EQUATES ARE BASED ON THIS VALUE)
;
DPORT EQU 090H ;UART DATA PORT
;
;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 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 TRIES TO GET IT RIGHT.
; 8. WHEN PASSWORD ENTERED, 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)
;
; SYSTEM EQUATES:
FALSE EQU 0
TRUE EQU NOT FALSE
BDOS EQU 5
CR EQU 0DH
LF EQU 0AH
;
MAX$DRIVE EQU 2 ;HIGHEST SUPPORTED DRIVE (0=A, 1=B, etc)
MAX$USER EQU 3 ;HIGHEST SUPPORTED USER
PRINTER EQU FALSE ;WANT TO RETAIN LIST DEVICE?
DUAL$IO EQU TRUE ;WANT CONSOLE & MODEM?
CALLBAK EQU TRUE ;WANT CALLBACK FEATURE?
PSWDREQ EQU FALSE ;PASSWORD REQUIRED?
FASTCLK EQU TRUE ;TRUE IF 4MHZ SYSTEM CLOCK
CPM2 EQU TRUE ;TRUE FOR CP/M VERSION 2.x
WBCMND EQU TRUE ;TRUE TO USE WARM BOOT COMMAND
WBUSER EQU 3 ;USER # FOR WARM BOOT COMMAND (MUST BE 0 IN 1.4 CP/M)
WBDRV EQU 0 ;DRIVE # FOR WARM BOOT COMMAND (0=A, 1=B, ETC.)
; (COMMAND STRING GOES AT LABEL 'WBCSTR' NEAR
; END OF PROGRAM)
TIMEOUT EQU TRUE ;TRUE IF TIMING OUT ON CONSOLE INPUT
TOVALUE EQU 20*5*60 ;TIMEOUT TIME IN 20THS OF A SECOND
;
; HAYES MODEM PORT ASSIGNMENTS:
;
;HAYES MODEM PORT EQUATES (DPORT PREVIOUSLY DONE)
;
TPORT EQU DPORT+1 ;CONTROL/STATUS PORT
RPORT EQU DPORT+1 ;RATE GEN/MODEM STATUS
CPORT EQU DPORT+2 ;MODEM CONTROL
;
;MODEM CONTROL COMMAND WORDS
;
P3CLEAR EQU 00H ;IDLE MODE
;
;
;
;SWITCH HOOK AND MODEM COMMANDS,
; OUTPUT TO TPORT (PORT 0)
;
P0BYE EQU 0 ;ON HOOK, OR DIALING BREAK
P0ORIG EQU 84H ;OFF HOOK, ORIG.
P0ANSW EQU 82H ;ANSWER PHONE
P08BIT EQU 06H ;8 DATA BITS
P0NOPY EQU 10H ;NO PARITY
P0EPS EQU 01H ;EVEN PARITY SELECT
P0TSB EQU 08H ;2 STOP BITS
P0EI EQU 20H ;ENABLE INTERRUPTS
P0NORM EQU P08BIT+P0NOPY ;I USE 8 BITS, NO PARITY
P0110 EQU P08BIT+P0NOPY+P0TSB ;SAME W/2 STOP BITS
;
;MODEM STATUS, INPUT ON TPORT (PORT 1)
;
P2RDET EQU 80H ;RING DETECT
P2CTS EQU 40H ;CTS (CARRIER DETECT)
;
;HAYES MODEM STATUS MASKS
;
P0TBMT EQU 2 ;XMIT BUFF EMPTY
P0DAV EQU 1 ;DATA AVAILABLE
P0RPE EQU 4 ;REC'D PARITY ERR
P0ORUN EQU 10H ;OVERRUN
P0FERR EQU 08H ;FRAMING ERROR
;
;BAUD RATE DIVISORS
;
B110 EQU 0 ;110 BAUD
B300 EQU 1 ;300 BAUD
;
ORG 100H
;
;MOVE THE MODEM INTERFACE PROGRAM UP TO HI RAM
;AND JUMP TO IT.
;
MOVEUP lxi sp,80h ;set a temporary stack
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 jump address
sub a ;force user 0, disk A
sta 4 ;at next sign-in
IF CPM2
mvi e,0 ;need to set user 0 in bdos
mvi c,32 ;so that open succeeds on welcome file
call bdos
ENDIF
mvi e,0
mvi c,14 ;also need drive A default
call bdos
mvi a,0C3H ;reset boot trap/control-c trap
sta 0
ret ;JUMP TO "START" (was PUSHed above)
;
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
;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 NOSLASH
;GOT AN OPTION - VALIDATE IT
INX H ;TO OPTION BYTE
MOV A,M ;GET IT
CPI 'A' ;ANSWER?
JZ ANSWER
;NO OPTION, OR INVALID ONE
NOSLASH EQU $+OFFSET
CALL CARCK ;SIGNED OFF W/THIS PROG?
JC HANGUP ;NOBODY THERE
CALL ILPRT ;PRINT THIS MSG:
DB CR,LF,'GOOD BYE, CALL AGAIN'
DB CR,LF,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
sub a ;force user 0, disk A
sta 4 ;at next sign-in
IF CPM2
mvi e,0 ;need to set user 0 in bdos
mvi c,32 ;so that open succeeds on welcome file
call bdos
ENDIF
mvi e,0
mvi c,14 ;also need drive A default
call bdos
mvi a,0C3H ;reset boot trap/control-c trap
sta 0
;
;CLEAR DTR CAUSING PHONE TO HANG UP
MVI A,P3CLEAR ;CLEAR..
OUT CPORT ;..DTR
;
; AWAIT RINGING
;
RINGWT EQU $+OFFSET
;CHECK LOCAL KEYBOARD FOR CTL-C EXIT REQUEST.
;NOTE: MUST DO DIRECT INPUT BECAUSE CBIOS PATCHES
;ARE NOT DONE UNTIL CALL COMES IN.
IN CONDATA ;CHECK LOCAL KBD
ANI 7FH ;STRIP PARITY BIT
CPI 'C'-40H ;CONTROL C?
JZ 0 ;YES, --EXIT-- TO CP/M
;
RINGW2 EQU $+OFFSET
IN RPORT ;GET THE STATUS
ANI P2RDET ;RINGING?
JNZ RINGWT ;NO, WAIT
;
;THE PHONE IS 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.
;
MVI L,45 ;DELAY 4.5 SECONDS FOR NEXT RING
WAITNX EQU $+OFFSET
CALL DELAY ;WAIT .1 SECONDS
DCR L ;MORE TO GO?
JNZ WAITNX ;YES?...LOOP
IN RPORT ;GET THE STATUS
ANI P2RDET ;RINGING AGAIN?
JNZ EXPECT ;NO?...ITS FOR ME!
;CALL NOT FOR COMPUTER - WAIT UNTIL RINGING DONE, THEN RESET
WAITNR EQU $+OFFSET
MVI L,100 ;WAIT FOR 10 SECS NO RINGING
WAITNRL EQU $+OFFSET
CALL DELAY ;DELAY .1 SECONDS
IN RPORT ;GET THE STATUS
ANI P2RDET ;STILL RINGING?
JZ WAITNR ;YES, WAIT 10 MORE SECONDS
DCR L ;NO RING, MAYBE WE'RE DONE
JNZ WAITNRL ;NO, LOOP SOME MORE
JMP HANGUP
;
EXPECT EQU $+OFFSET
LXI H,400 ;40 SECONDS TO REDIAL
RELOOK EQU $+OFFSET
IN RPORT
ANI P2RDET ;RINGING AGAIN?
JZ ANSWER
CALL DELAY
DCX H
MOV A,H
ORA L
JNZ RELOOK
JMP HANGUP
;
ENDIF ;END OF CALLBACK ROUTINES
;
;SETUP MODEM
ANSWER EQU $+OFFSET
MVI A,P0ANSW ;TURN ON
OUT CPORT ;..DTR
MVI E,20
ANSWR1 EQU $+OFFSET
CALL DELAY ;GIVE TIME TO TURN ON
DCR E
JNZ ANSWR1
MVI A,P0110
OUT TPORT ;ANSWER PHONE
CALL DELAY ;GIVE TIME FOR ANSWER
IN CONDATA ;CLEAR LOCAL KBD PORT
IN DPORT ;CLEAR MODEM PORT
IN DPORT ;MAKE SURE ITS CLEAR
;OUTPUT VALUE ALLOWING MODEM TO HANG UP ON
;LOSS OF CARRIER
CALL CARCK ;LOOK FOR CARRIER
JC HANGUP ;AWAIT ANOTHER CALLER
;NOW TEST INPUT FOR BAUD RATE
CALL PATCH ;PATCH JMP TABLE
CALL TSTBAUD ;SEE IF BAUD = 110
JZ WELCOME ;YES, EXIT
MVI A,P0NORM ;SET FOR 1 STOP BIT, ETC.
OUT TPORT
MVI A,B300+P0ANSW ;SET DIVISOR
OUT CPORT ;.. TO 300 RATE
CALL TSTBAUD ;SEE IF BAUD = 300
JZ WELCOME ;YES, EXIT
CALL UNPATCH ;RESTORE ORIG BIOS JMP TBL
JMP ANSWER ;TEST MORE - INVALID BAUD RATE
;
;WELCOME TO THE SYSTEM
;
WELCOME EQU $+OFFSET
;
GETNULL EQU $+OFFSET
CALL ILPRT ;PRINT THIS MSG:
DB CR,LF
DB 'HOW MANY NULLS 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
GETULC EQU $+OFFSET
CALL ILPRT
DB CR,LF,'CAN YOUR TERMINAL DISPLAY LOWER CASE? ',0
MVI A,20H
STA ULCSW ;FORCE CASE CONVERSION FOR NOW
CALL MINPUT ;GET Y OR N
MOV C,A
CALL MOUTPUT ;ECHO
CPI 'N'
JZ DONEOPT ;WE'RE ALREADY SET UP FOR NO LOWER CASE
CPI 'Y'
JNZ GETULC ;WASN'T Y OR N...RE-ASK
SUB A
STA ULCSW ;SET FLAG FOR NO CONVERSION
DONEOPT EQU $+OFFSET
CALL ILPRT
DB CR,LF,0
;PRINT THE WELCOME FILE
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
;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
;
;GET THE PASSWORD
;
PASSINT EQU $+OFFSET
IF PSWDREQ
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
IN DPORT ;CLEAR OUT GARBAGE
PWMLP EQU $+OFFSET
CALL MINPUT ;GET A CHAR
CPI 'U'-40H ;CTL-U?
JZ PASSINP ;YES, RE-GET IT
CPI 60H ;LOWER CASE?
JC NOTLC ;NO,
ANI 5FH ;MAKE UPPER CASE ALPHA
NOTLC EQU $+OFFSET
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
ENDIF
;PASSWORD CORRECT
CALL ILPRT
DB CR,LF,'BOOTING SYSTEM...',0
IF WBCMND
MVI A,0FFH ;SET WARM BOOT FLAG (TESTED AT MOUTPUT)
STA WBFLAG
ENDIF
JMP VWARMBT ;GO LOAD CP/M
;
;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
CPI CR ;IF A CARRIAGE RETURN...
RZ ;.. RETURN
CPI LF ;IF A LINEFEED...
RET ;RET ZERO FLAG, ELSE NOT ZERO
;
; LOSS OF CONNECTION TEST
;
;THIS ROUTINE AUTOMATICALLY HANGS UP THE
;PHONE AFTER LOSS OF CARRIER
;
;THIS ROUTINE CHECKS IF CARRIER IS STILL
;PRESENT, AND IF SO, RETURNS WITH CARRY CLEAR.
;IF NOT, IT WAITS FOR CARRIER FOR 15 SECS.
;IF THIS TIME RUNS OUT, IT RETURNS WITH CARRY SET.
;
;
CARCK EQU $+OFFSET
PUSH D
MVI E,150
CARCK1 EQU $+OFFSET
IN RPORT ;LOOK AT STATUS
ANI P2CTS ;GET CARRIER DETECT BIT
JNZ CARCK2 ;IF CARRIER ON, continue with checks
;LOOP UNTIL EITHER TIME EXHAUSTED, OR
;CARRIER RETURNS
CALL DELAY ;KILL .1 SEC
DCR E ;COUNT DOWN TIME
JNZ CARCK1
STC
pop d
ret
CARCK2 EQU $+OFFSET
lda 4 ;check disc/user #
ani 0fh ;isolate drive
cpi max$drive+1 ;valid drive?
jc carck3 ;yes, skip this junk
lda 4 ;restore whole login byte
ani 0f0h ;retain user #
sta 4 ;force drive to A
jmp 0 ;force warm boot (punishment?)
carck3 equ $+offset
if cpm2 ;skip this junk if cp/m 1.x
lda 4 ;re-fetch login byte
ani 0f0h ;isolate user #
cpi max$user*16+1 ;valid user ?
jc carck4 ;yes, don't change
lda 4 ;refresh login byte again
ani 0fh ;keep drive, zero user
sta 4
jmp 0 ;force warm boot
endif ;end of cp/m 2.x dependant stuff
CARCK4 EQU $+OFFSET
ora a ;clear carry
POP D
RET
;
; .1 SEC DELAY ROUTINE
;
DELAY EQU $+OFFSET
PUSH B
IF FASTCLK
LXI B,16667 ;.1 SEC COUNT FOR 4MHZ SYS CLOCK
ENDIF
IF NOT FASTCLK
LXI B,8334 ;.1 SEC COUNT FOR 2MHZ SYS CLOCK
ENDIF
DELAY1 EQU $+OFFSET
DCX B ;COUNT DOWN DELAY TIME
MOV A,B
ORA C
JNZ DELAY1 ;CONTINUE COUNTING TILL DONE
POP B
RET
;
;
KDELAY EQU $+OFFSET
PUSH B
IF FASTCLK
LXI B,8334 ;.05 SEC COUNT FOR 4MHZ
ENDIF
IF NOT FASTCLK
LXI B,4167 ;.05 SEC COUNT FOR 2MHZ
ENDIF
JMP DELAY1
;
;
;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
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 NOT PRINTER
MVI B,18 ;BYTES TO MOVE
ENDIF
;
IF PRINTER ;RETAIN LIST DEVICE?
MVI B,15 ;DON'T MOVE LISTER JUMP
ENDIF
;
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 STATUS, AND 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
DB '++CARRIER LOST++'
DB 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
;
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
;
;KEYBOARD/MODEM STATUS TEST ROUTINE
;
MSTAT EQU $+OFFSET
;
IF DUAL$IO ;WANT LOCAL CONSOLE?
CALL CONSTAT ;GET LOCAL STATUS
ORA A
RNZ ;RET IF LOCAL CHAR
ENDIF
;
IN TPORT ;GET STATUS
ANI P0DAV ;DATA AVAILABLE?
RZ ;RETURN IF NOT READY
IN TPORT ;GET STATUS AGAIN
ANI 18H ;CHECK FRAMING AND OVERRUN BITS
JZ MSTAT1 ;NO ERRORS...LEGIT CHARACTER
IN DPORT ;SWALLOW CHARACTER (CLEARS P0DAV)
SUB A ;RETURN FALSE (0)
RET
MSTAT1 EQU $+OFFSET
MVI A,0FFH ;SHOW READY
ORA A
RET
;
;MODEM INPUT FUNCTION, CHECKS LOCAL CONSOLE FIRST
;
MINPUT EQU $+OFFSET
IF TIMEOUT
PUSH H ;INITIALIZE TIMEOUT COUNTER
LXI H,TOVALUE
SHLD TOCNT
POP H
ENDIF
MINPUT1 EQU $+OFFSET
LDA LOSTFLG ;KNOWN LOSS..
ORA A ;..OF CARRIER?
CZ CHECK ;CARRIER STILL ON?
;
CALL MSTAT ;ANYTHING?
ORA A
;
IF NOT TIMEOUT
JZ MINPUT ;LOOP TILL CHAR RCD
ENDIF
;
IF TIMEOUT
JNZ MINPUT2
CALL KDELAY ;KILL .05 SEC
PUSH H
LHLD TOCNT ;KNOCK DOWN TIMEOUT COUNTER
DCX H
SHLD TOCNT
MOV A,H
ORA L
POP H
JNZ MINPUT1 ;STILL MORE TIME...KEEP TRYING
CALL ILPRT
DB '+++INPUT TIMED OUT',7,7,0
JMP NOSLASH
ENDIF
;
;GOT CHAR - SEE WHICH PORT
;
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
;
;LOCAL CONSOLE WASN'T READY, SO READ MODEM
IN DPORT ;GET DATA BYTE
ANI 7FH ;DELETE PARITY
JZ MINPUT ;IGNORE NULLS
IF WBCMND
CPI 3 ;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 AS TYPED
RZ
SUB A ;ELSE CONVERT IT TO A NULL
ENDIF
RET
;
;MODEM OUTPUT ROUTINE. OUTPUTS TO MODEM,
;THEN TO LOCAL CONSOLE
;
MOUTPUT EQU $+OFFSET
;IF WE ALREADY KNOW CARRIER IS LOST,
;DON'T CHECK FOR IT AGAIN
LDA LOSTFLG ;KNOWN LOSS OF CARRIER?
ORA A
CZ CHECK ;CARRIER STILL ON?
IF WBCMND
LDA WBFLAG ;IS THIS FIRST WARM BOOT SINCE SIGNON?
ORA A ;IF NOT, SKIP THIS STUFF
JZ MOUTP1
SUB A ;TURN OFF FLAG FOR NEXT TIME
STA WBFLAG
MVI A,0CDH ;DISABLE WARM BOOT
STA 0
LDA 7 ;GET BDOS ADDRESS
SUI 8 ;CCP IS 2K DOWN FROM BDOS
MOV H,A
MVI L,0 ;HL NOW CONTAINS CCP ENTRY ADDRESS
PUSH H ;SAVE FOR LATER
MVI L,7 ;POINT TO BYTE COUNT IN CCP COMMAND BUFFER
XCHG ;MAKE IT DEST POINTER (DE)
LXI H,WBCSTR ;POINT TO COMMAND STRING TO DROP IN
MOV B,M ;GET BYTE COUNT
INR B ;UP BY 2 TO INCLUDE COUNT AND TRAILING NULL
INR B
CALL MOVE ;DROP IT IN TO CCP
MVI A,WBUSER*16+WBDRV ;SET LOCATION 4 (USER/DRIVE)
STA 4
MOV C,A ;ALSO PASS IT TO CCP
POP H ;GET BACK CCP ENTRY ADDRESS
PCHL ;GO THERE
MOUTP1 EQU $+OFFSET
ENDIF
IN TPORT ;READ MODEM STATUS
ANI P0TBMT ;XMIT BUFF EMPTY?
JZ MOUTPUT ;LOOP IF NOT READY
MOV A,C ;GET CHAR
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
OUT DPORT ;OUTPUT TO MODEM
;
IF DUAL$IO ;TO LOCAL ALSO?
CALL CONOUT ;SEND TO REGULAR BIOS
ENDIF
;
;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
;
;ACCESS PASSWORD (ENDS IN C/R)
;
PASSWD EQU $+OFFSET
DB '******' ;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,0,0
;
;WARM BOOT COMMAND STRING
;
IF WBCMND
WBCSTR EQU $+OFFSET
DB WBCEND-WBCSTR-2
DB 'RIBBS'
DB 0
WBCEND EQU $+OFFSET
ENDIF
;
;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
POP H
POP D
POP B
RET
;
CONOUT EQU $+OFFSET
PUSH B
PUSH D
PUSH H
CALL VCONOUT
POP H
POP D
POP B
RET
;
; 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 MBOOT ;BOOT TRAP
JMP MBOOT ;BOOT TRAP
JMP MSTAT ;MODEM STATUS TEST
JMP MINPUT ;MODEM INPUT ROUTINE
JMP MOUTPUT ;MODEM OUTPUT ROUTINE
RET ;DUMMY LIST DEVICE
NOP
NOP
;
WELFILN EQU $+OFFSET
DB 0,'WELCOME ',0
;WELCOME FILE NAME ^^^^^^^^^^^
;
NULLS EQU $+OFFSET
DB 5
WBFLAG EQU $+OFFSET
DB 0
TOCNT EQU $+OFFSET
DW 0
ULCSW EQU $+OFFSET
DB 0
;
PEND EQU $+OFFSET ;END OF RELOCATED CODE
;
;KEEP TRACK OF LOST CARRIER WHEN TYPING
;"++CARRIER LOST++" SO WE DON'T LOOP
;
LOSTFLG EQU $+OFFSET
DS 1
;
;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
;
DS 60
STACK EQU $+OFFSET ;LOCAL STACK
;
WRCON EQU 2
OPEN EQU 15
READ EQU 20
STDMA EQU 26
FCB EQU 5CH
FCBRNO EQU FCB+32
;
END