home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
beehive
/
zcat
/
zbye12z.mac
< prev
next >
Wrap
Text File
|
1994-07-13
|
40KB
|
1,604 lines
.sall
.sfcond
; Program: ZBYE
; Author: Jay Denebeim
; Assembler: M80 Version 3.44 or greater. (SLRMAC ETB)
version equ 12
rev equ 'Z'
;
; ZCPR Bye RCP
;
; This program implements BYE as an RCP under ZCPR3. It handles all modem
; IO by replacing the console routines. All other functions are passed to
; the ZCPR CCP for execution. Where BYE normally uses equates, I.E. password
; connection, carrier lost commands, etc., ZBYE passes command lines to ZCPR.
; This should reduce the bugs introduced by tons of conditional assemblies
; that has plagued the recent versions of BYE. It has also allowed room to
; do more functions than BYE normally has done in the past. Please folks,
; lets keep the conditional assemblies down to a minimum.
;
; There are several new features in this program:
; Since its an RCP BYE can remain resident while the SYSOP is using
; the computer locally. ZBye will answer the phone while in this mode,
; and allow the operator to accept the call while in another program.
; A chat mode has been implemented, this allows either single way, or
; two way communication between the sysop and the caller.
; It will also allow changes of the Maximum drive and user area
; without disabling the modem IO.
;
; The function key descriptions:
; ^L - Toggle Local only IO. This toggles the modem IO on and off.
; ^O - Toggle Open access. This switches the wheel, maxdrive, and
; maxuser bytes of ZCPR3. NOTE: this is the location your
; BBS, XMODEM, and whatever else should check. Its no longer
; in the BYE header. Also, be sure to watch the user while
; he's on in this mode, either disable the modem, or be ready
; with the ^N.
; ^N - Nerdkey, Hang up on the bozo
; ^Q - Query the user, (CHAT mode), end with ^C. This is a very
; rudimentrary chat. If local only, he can't type back,
; but if not, its two way. Be sure to announce yourself
; 'cause ZBYE doesn't anounce when its going into chat mode.
; the only editing commands implimented are expansion of
; <cr> to <cr><lf>.
;
; To install this program, install your terminal dependent code following
; the .8080 psudo-op. ZBYE was set up to use MBYE overlays, these are either
; very similar, or identical to BYE2.x or 3.x overlays. Remember that
; EQUates can't have :'s in front of them for M80, so you'll probably have
; to do a global replace of :^IEQU with ^IEQU. I'd really appreciate it if
; you would send me a copy of your overlay when you finish it.
; You will also have to change the terminal dependent cursor
; functions to match your own system.
;
; This program is the first in a series of ZCPR RCPM software. Look for
; ZBBS, ZXMODEM, ZDIR, and ZCHAT at a RCPM near you.
;
; Copyright 1985, by Jay Denebeim. This program is released to the public
; domain. It can be freely given, but under no circumstances will this
; software be charged for, except a copying fee not to exceed the price of
; the media copied to.
;
; I hope you enjoy using this program as much as I enjoyed writing it.
; If you make any modifications to this program, or have any suggestions,
; please feel free to contact me.
; Thanks a bunch,
; Jay Denebeim
; 1800 Williamsburg Rd Apt 13-E <- NOTE: Address and phone number new.
; Durham, NC 27707
; (919) 489-1785 (voice)
; (919) 489-6737 (data)
;
;-----------------------------------------------------------------------
;
; Revision History:
;
; 1.2Z Extensive revisions to accomodate a dumb UART which cannot detect
; carrier or cause the modem to answer or hangup. Code reorganized
; to place all UART code in one place where it can be handled as
; an overlay, all modem code in another overlay (smart or dumb)
; and all terminal code in another overlay (25th line for status
; or not). Added conditional code generation to prevent meddling
; with the wheel byte if z3whl=0.
; Earl T. Boone
;
; 1.2A *** Release Version *** Fourth public release.
; Implemented answer routines for a dumb modem. Set the equate
; DUMB to yes and baud rate will be set by carriage return
; sence. Also moved initializing modem message to the right place.
; Jay Denebeim 09/08/85
;
; 1.1F Added equates for most major functions of this program. Also moved
; the command lines to the top of the file so they're easier to find.
; Please, when adding functions, make sure they turn all the way off
; CREF is great for finding code that isn't used when functions are
; turned off. Jay Denebeim 09/14/85
;
; 1.1E Added KILCALR equate. This switches on routines that will kill
; the caller if the byte at 0 is not equal to C3. NOTE: this brought
; the size over the limit on my system. The dumb modem routines
; are enough smaller that this will fit in dumb mode.
; Jay Denebeim 09/09/85
;
; 1.1D Added an equate to allow the printer to be enabled by the wheel.
; Set the LSTDEV equate to YES if you want the printer available
; while ZBye is running. Do be careful with this, most CP/M systems
; lock up if the printer is not on-line during an attempt to print.
; Don't run any programs that print remotely unless you're sure the
; printer is on-line. Jay Denebeim 08/19/85
;
; 1.1C *** Release Version *** Third public release.
; While modifing LUX4.0 to 4.1, I was reminded that time outs are
; very similar to carrier losses. So, the carrier loss interupt
; also means time out. To the program running under ZBYE, the reason
; for the loss of user isn't important. Jay Denebeim 02/15/85
;
; 1.1B Made Wheel on status line follow what the wheel was actually
; set to. Input Timed out msg was in the wrong place, and was erased
; when bye ran again. Jay Denebeim 02/02/85
;
; 1.1A *** Release Version *** Second public release.
; Cleaned up the comments, and stripped out the modem dependent
; routines. Jay Denebeim 01/11/85
; 1.0G Changed carrier lost routine to restart # 30 so that programs
; could do their own thing on CLOSS. Added check for wheel change
; so the sysop drives would follow the wheel.
; Jay Denebeim 01/11/85
; 1.0F Moved BYE initialization routines into low memory. This freed
; up some memory, and allowed another bit to implement another
; routine. This routine runs a set of programs before hanging
; the modem up Jay Denebeim 01/10/85
; 1.0E Moved local char status, and bye mode bytes into low memory
; so they will be available for other programs.
; Jay Denebeim 01/09/85
; 1.0D If wrong characters typed during local mode answer, the caller
; would get hung up on. Jay Denebeim 01/09/85
; 1.0C Reduced the size of the program. RCP was overflowing.
; Jay Denebeim 01/08/85
; 1.0B Answer phone while in local mode. Jay Denebeim 01/07/85
; 1.0A First public release. by - Jay Denebeim 12/23/84
;
;-----------------------------------------------------------------------
;
;
; Equates for this program
;
.xlist
maclib E:Z3BASE.LIB
.list
;
no equ 0
yes equ not no
cr equ 0dh ; carriage return
lf equ 0ah ; line feed
;
bdos equ 5
bios equ 0
;
mhz equ 20 ; CPU speed times 10
closs equ 1 ; Number of seconds to wait after loss of carrier
clrou equ 30h ; Routine to call on loss of carrier
jump equ 0c3h ; 8080/Z80 jump instruction
;
; Conditional assembly macros. Use these to switch functions on and
; off.
;
etb equ yes ; Special functions for Earl T Boone
;
obye equ no ; Emulate BYE3.x ?
dumb equ no ; Is this system running under a dumb modem?
lstdev equ no ; Enable printer when wheel is set?
kilcalr equ yes ; Kill the caller if memory location 0 <> C3
timeout equ yes ; yes, auto logout for sleepy callers
tomins equ 2 ; minutes to auto logout
tmins equ ((tomins*mhz)+5)/10 ;(don't change this one...)
statln equ no ; display the status on line 25
; (see terminal dependent section)
chatf equ yes ; provide chat function
lclans equ yes ; answer modem while in local mode
;
cdrive equ 'E'-'@' ; Callers Maximum Drive
cuser equ 31 ; Callers Maximum User Area
;
lclst equ 003bh ; Local Console generated character flag
bymode equ 003fh ; Bye control byte
;
; The BYE mode byte is bit mapped and has the following attributes:
;
bymmio equ 80h ; 7 = Modem IO enable
bymcio equ 40h ; 6 = Console IO enable
bymica equ 20h ; 5 = Ignore Carrier
bymncc equ 10h ; 4 = Next Caller Commands Running
bymclc equ 08h ; 3 = Carrier Lost Commands Running
bymnor equ 04h ; 2 = Normal Mode Commands Running
bymaoc equ 02h ; 1 = Alert Operator on Call
bymphu equ 01h ; 0 = Pre-Hangup Commands Running
;
;-----------------------------------------------------------------------
;
; Global Macros
;
cmdln macro cmd
local cmdst,msg,cmdend
cmdst: dw z3cl+msg-cmdst
db z3cls,0
msg: db cmd
db 0
cmdend:
endm
;-----------------------------------------------------------------------
;
; Command line macros
;
byecl macro ; Executed during initialization
cmdln 'BYE'
endm
;
gbcl macro ; Executed before normal disconnection
cmdln 'BYE'
endm
;
nccl macro ; Executed between calls
; cmdln 'A0:;LDR RCPM.NDR;PATH A0:;BYE' ; JD's original
cmdln 'A0:;PATH E0: A0: A15: E0:;BYE' ; ETB's revision
endm
;
nmcl macro ; Executed upon connection
; cmdln 'A0:;RBBS;MENU' ; JD's original
cmdln 'E0:;LDSK B:;LDSK C:' ; ETB's revision
endm
;
clcl macro ; Executed if carrier lost
cmdln 'BYE'
endm
;
tocl macro ; Executed if timed out
cmdln 'BYE'
endm
;
kccl macro ; Executed if call killed by higher process
cmdln 'BYE'
endm
;
;-----------------------------------------------------------------------
; TPA starts here
;-----------------------------------------------------------------------
;
; Lets get this show on the road
;
MACLIB Z80
aseg
org 100h
;
; Lets see if BYE is already resident.
;
lxi h,rcp ; Point to RCP area
lxi d,bybeg ; Point to RCP's name
lxi b,5 ; Length of name
chbye1: ldax d ; Get next char
cci ; Is it the same?
jrnz nbye ; Nope, re-locate the RCP
jpo ybye ; If done, its there
inx d ; Point to next char
jr chbye1 ; Do it again
;
nbye: mvi c,9
lxi d,nbst
call 5
xra a
sta lclst ; Clear out local status
sta bymode ; and Bye's operating mode
lxi h,bybeg
lxi d,rcp
lxi b,byend-bybeg
ldir ; Re-Locate BYE
mvi a,jump ; load A with JUMP instruction
sta clrou ; and put in restart
lxi h,lostit ; do the same
shld clrou+1 ; with original closs command line
call byeini
jmp ybye
nbst: db 'ZBye version '
db '0'+(version/10), '.', '0'+(version mod 10), rev
db ' - By Jay Denebeim Copyright (C) 1985',cr,lf
db 'Making BYE',cr,lf,'$'
;
ybye: lxi h,bye
lxi d,z3cl
lxi b,byelen
ldir ; Load 'BYE' into command line
;
jmp 0
;
bye: byecl
byelen equ $-bye
;
byeini: lda z3env+2ch ; store away, sysop's Highest drive
sta sdrive
lda z3env+2dh ; and user area.
sta suser
lda fstprv ; Store first letter of private
sta prvlet ; commands
call newbio
call clrbuf
call modini
mvi a,bymmio+bymcio+bymica+bymclc
sta bymode
ret
;
; The folowing code should logically be located in the UART and MODEM
; hardware specific overlay area of the code. It is located here
; to save space in the RCP by doing these initialization functions
; (only executed once) in the TPA.
;
; Initialize the UART (interface to modem)
;
modini:
call mdinit ; Initialize serial port
mvi b,3
call ldelay ; delay .3 sec
call mdansw ; raise dtr
call delay
call set1200 ; 1200 baud
call delay
mvi a,bymmio+bymica
sta bymode ; enable modem io
if not dumb
call prinlo ; reset modem
db 'ATZ',cr+80h ; at this point we don't know
; whether the command will be echoed
; or whether the status will be
; numeric or verbal
call l2char ; is it status
cnz l2char ; if not - try again
;
; the next command will echo or not based strictly on the physical
; switches on the modem itself
;
call prinlo ; set our way
db 'ATS0=0' ; never answer
db 'V0' ; numeric status codes
db 'E0' ; no command echo
db 'X1' ; extended status
db 'M1',cr+80h ; speaker off at connect time
call l2char ; get echo
cnz l2char ; get status
jnz modini ; status ok?
endif ; dumb
ret
;----------------------------------------------------------------------
; RCP starts here
;----------------------------------------------------------------------
bybeg:
.phase rcp
db 'ZBYE ' ; RCP's name for ZCPR
db 3 ; Command name length
fstcmd: db 'BYE'
dw start
fstprv: db 'OFF'
dw byeoff
db 0
;
start:
pop h ; Get ZCPR3's return address
shld z3ret ; Save it
lxi h,bymode
bit 0,m
jnz prophu ; Process pre-hangup commands
bit 1,m
jnz prolcl ; Process a local exit
bit 2,m
jnz pronor ; Process a normal exit
bit 3,m
jnz proclc ; Carrier lost commands finished
bit 4,m
jnz proncc ; Next caller commands finished
call prinpl
db 'Invalid BYE mode! BYE terminating',7,cr,lf+80h
jr byeof1
;
byeoff:
pop h ; Get ZCPR3's return address
shld z3ret ; Save it
byeof1: call oldbio
mvi a,0
sta rcp ; Disable RCP recognition
sta fstcmd ; and for the CCP
lxi h,bymode
res 7,m ; Turn off modem IO
if statln
call prinlc
enab25 no
cls yes ; enable 25th line and clear screen
endif ; statln
call prinpl
db 'Bye is gone',cr,lf+80h
jmp exit
;
; Local storage initialized by loader
sdrive: db 0 ; sysop's max drive
suser: db 0 ; sysop's max user
prvlet: db 0 ; priviledged letter
;
; Process pre-hangup commands
;
prophu: mvi a,bymcio+bymmio+bymnor ;con enab, modem enab, normal caller
sta bymode
;
lxi h,gbcmd ; Load next command string
lxi b,gblen
lxi d,z3cl
ldir
jmp exit
;
gbcmd: gbcl
gblen equ $-gbcmd
;
; Process a local exit, actually a modified normal answer, but must check
; for carrier present.
;
prolcl: call mdcarck
jrz prolc1 ; If no carrier, just get ready for next call
mvi a,0ffh ; set flag
sta prlct1
jr prolc2 ; get ready for next caller
;
prlct1: ds 1
;
; Process a normal exit. This routine runs any programs to end the
; session, says Bye, hangs up the modem, turns off the modem IO,
; then runs the routines to get ready for the next caller.
;
pronor: call prinpl
db 'Goodbye, call again soon!',cr,lf+80h
;
prolc1:
call prtsta
db 60,,13
;
; If carrier lost, no point in printing msg
;
proclc:
call mdinit
prolc2: mvi a,bymcio+bymncc ;con enab, nxt calr mode
sta bymode
;
call clrbuf
call ressec
;
lxi h,nccmd ; Load next command string
lxi d,z3cl
lxi b,nclen
ldir
jmp exit
;
nccmd: nccl
nclen equ $-nccmd
;
; Ready for next caller. Set secure mode, then wait for arrival.
;
proncc:
call cursoff ; turn off cursor
call prtsta
db 40,,19
call clrscr ; clear screen
call setsec
mvi a,bymcio+bymphu
sta bymode
lda prlct1 ; ending local mode ?
cpi 0ffh
push psw
xra a
sta prlct1 ; zero it anyway
pop psw
jrz pronc2
call nxtcal
pronc1: call modans
call mdcarck ; No Carrier?
jrz pronc1 ; Then loop
pronc2:
call curson ; turn cursor on
call prtsta
db 60,'Connected',0
lxi h,bymode
setb 7,m ; Make sure modem is on
res 5,m ; and carrier significant
call prinpl
db 'Welcome to ZBoard',cr,lf
db 'You are now running under ZBYE version '
db '0'+(version/10), '.', '0'+(version mod 10), rev, cr, lf+80h
;
lxi h,nmcmd ; Load normal entry command string
lxi d,z3cl
lxi b,nmlen
ldir
jmp exit
;
nmcmd: nmcl
nmlen equ $-nmcmd
;
; Set ZCPR into a secure mode
;
if z3whl
setsec: call usrdru
xra a
sta z3whl ; Clear the wheel
sta fstprv ; And private commands
ret
;
; Set highest drive and user area for caller.
;
usrdru: mvi a,cdrive ; Set Caller's highest drive
sta z3env+2ch
mvi a,cuser
sta z3env+2dh ; and user area.
push psw
push h
call prtsta
db 40,'Not Wheel',0
pop h
pop psw
ret
else
setsec: ret ; not a secure system
endif ;z3whl
;
; Set ZCPR into sysop mode
;
if z3whl
ressec: call sysdru
xra a
cma
sta z3whl ; Set the wheel
lda prvlet ; and private commands
sta fstprv
ret
;
; Set highest drive and user area for SysOp.
;
sysdru: lda sdrive ; Set Sysop's highest drive
sta z3env+2ch
lda suser
sta z3env+2dh ; and user area.
call prtsta
dc 40,' Wheel',0
ret
else
ressec: ret ; not a secure system
endif ;z3whl
;
; Clear ZCPR's internal buffers
;
clrbuf: xra a
;
if z3env
lxi h,z3env+80h ; Clear TCAP area
lxi d,z3env+81h
lxi b,7eh ; TCAP length-1 (always?)
mov m,a
ldir
endif ;z3env
;
if shstk
lxi h,shstk ; Clear Shell Stack
lxi d,shstk+1
lxi b,shstks*shsize-1
mov m,a
ldir
endif ;shstk
;
if z3msg
lxi h,z3msg ; Clear Message Buffers
lxi d,z3msg+1
lxi b,4eh ; Message buffer length -1
mov m,a
ldir
endif ;z3msg
;
ret
;
; Answer modem and wait for carrier. Set baud as appropriate.
;
modans:
call prtsta
db 30,'Awaiting Call',0
mdans00 call modans0
rz
cpi 'C'-'@' ; Control C from console?
jnz mdans00 ; Nope
lxi h,bymode
bit 1,m ; if in local bye active mode
jnz mdans00 ; then forget the console
res 7,m ; inhibit modem IO
setb 1,m ; go into local bye active mode
res 0,m ; make sure not in pre-hangup
call ressec
call curson ; turn on cursor
call prtsta
db 60,'Local',7
if lclans
jmp exit
else
jmp byeof1
endif ; lclans
;
; Get ready for next caller
;
nxtcal:
if timeout
xra a ; Clear timeout
sta tocnt
sta tocnt+1
mvi a,tmins
sta toval
endif ;timeout
;
call mdinit ; drop DTR
mvi b,3
call ldelay ; wait awhile
call mdansw ; raise it
call delay
call set1200
call delay
call sync ; synchronize modem
;
if lclans
; Check for call coming in during local mode. If so, answer it.
;
chkcal: lda chkt1
ora a
rnz ; return if already doing function
call mdcarck ; check for call still in progress
jrnz chkca4 ; yup
xra a
sta chkt2 ; he's gone
chkca4: lda chkt2
ora a ; if this function already run
rnz ; return to caller
mov a,m ; Get BYMODE
sta chkt1 ; indicate function running
push psw
res 6,m ; Turn off console
setb 7,m ; Turn on modem
setb 5,m ; Ignore Carrier
call incmcl ; check for incoming call
jz chkca1
call mdcarck ; Got carrier?
jz chkca1 ; Nope
lxi h,bymode
res 6,m
push h
call prinpl
db cr,lf,'Asking SYSOP if you can get on.',cr,lf+80h
call mdcarck ; Hung up?
jz chkca1 ; Oh well
chkca2: call oconst
jrz chkca3
call conin
jr chkca2 ; Eat console characters if any
chkca3: if statln
call go25
call prinlc
curpos 0,24,no
else
call prinlc
endif ; statln
dc 'Caller, let on ? '
call oconin
sta chkt1
if statln
call no25
endif ; statln
call mdcarck ; Still with us?
pop h
jrz chkca1 ; Nope, his loss
setb 7,m
res 6,m ; Set for remote IO
lda chkt1
ani 'Y'
cpi 'Y'
jrz letliv ; If Y or y let him on
call prinpl
db 'Sorry, try again later',cr,lf+80h
call nxtcal
jr chkca1
letliv: call prinpl
db 'He will let you on soon, please hold',cr,lf+80h
mvi a,0ffh
sta chkt2 ; indicate call in progress
chkca1: xra a
sta chkt1 ; zero out storage
pop psw ; Get original BYMODE
sta bymode
ret
chkt1: ds 1
chkt2: ds 1
;
endif ; lclans
;
; Check for carrier available. If not there, return with zero flag set.
;
carok: push h ; Do we care?
lxi h,bymode
bit 5,m
pop h
rnz ; Nope
push b
mvi b,closs*10
carok1: call mdcarck ; Got carrier?
jrnz carok2 ; Yup, great
call delay ; nope, wait awhile
djnz carok1 ; try again
carok2: pop b
ret
;
; Carrier lost. Drop Dead.
;
lostit: lda clgat
ora a
jrnz lstit1 ; Check for no status gate
;
call prtsta
db 60,'Carrier Lost',0
;
mvi a,bymcio+bymclc
sta bymode
lxi h,clcmd ; this is what we want to do
lxi d,z3cl ; point to zcpr's command line
lxi b,cllen
ldir
lstit1:
mvi a,jump ; just to be safe
sta 0
xra a
sta clgat ; Clear no status gate
jmp 0 ; Gotta exit this way
;
clcmd: clcl
cllen equ $-clcmd
clgat: db 0 ; gate for carrier lost command
;
if timeout
;
; Must be too late at night. He's asleep.
; Input timed out.
;
timout:
if etb
mvi a,0
sta carion ; mark 'carrier off'
endif
mvi a,0ffh
sta clgat ; Flag the timeout
call prinpl
db 'Input timed out',7,cr,lf+80h
call prtsta
db 60,'Timed Out',3
;
mvi a,bymcio+bymclc
sta bymode
lxi h,tocmd ; this is what we want to do
lxi d,z3cl ; point to zcpr's command line
lxi b,tolng
ldir
rst clrou/8 ; Do a CLOSS restart
;
tocmd: tocl
tolng equ $-tocmd
;
endif ;timeout
;
if kilcalr ; allow programs to commit suicide
;
; Memory Location 0 not C3H program abort
; If the base of memory is not a jump instruction, this routine will
; be executed. It is similar to a carrier lost, or timeout routine.
; Any program which changes the byte will cause the caller to be
; dropped unceremoniously.
;
kilcal: mvi a,0ffh
sta clgat ; Set the gate
mvi a,jump
sta 0 ; replace the jump instruction
call prtsta
db 60,'Call Killed',1
;
mvi a,bymcio+bymclc
sta bymode
lxi h,kccmd ; this is what we want to do
lxi d,z3cl ; point to zcpr's command line
lxi b,kclng
ldir
; rst clrou ; Do a CLOSS restart
rst clrou/8 ; assembler uses other syntax
;
kccmd: kccl
kclng equ $-kccmd
endif ; kilcalr
;
; Routines which process local function keys.
;
; Here are the descriptions
; ^L - Toggle Local IO
; ^O - Toggle Open access
; ^N - Nerdkey, Hang up on the bozo
; ^Q - Query the user, (CHAT mode)
;
fkeys: lxi h,bymode ; BYE in inactive state?
bit 1,m
rnz ; Yes, return
cpi 'L'-'@' ; Control-L ?
jrz toglcl ; if so, toggle local mode
cpi 'O'-'@' ; Control-O ?
jrz togope ; Yes? Toggle security
cpi 'N'-'@' ; Control-N ?
jz twitem ; Goodbye bozo
;
if chatf
cpi 'Q'-'@' ; Control-Q
jz bychat ; Go into Chat Mode
endif ;chatf
;
ret ; Not a BYE function Key
;
; Toggle Local IO Mode
;
toglcl: bit 7,m
jrz toglc1 ; If set, reset it.
res 7,m
call prtsta
db 51,'Local Disabled',0
jr endfun
toglc1: setb 7,m
call prtsta
db 51,'Local',8
jr endfun
;
; Toggle Security
;
togope: lda fstprv
ora a ; Secure?
jrz togop1 ; If so, remove it
call setsec ; Turn on security
jr endfun
togop1: call ressec ; Turn it off
jr endfun
;
; Hang up on the bum.
;
twitem:
call curson
call prtsta
db 60,'Twitted off',0
jmp proclc ; Same as Carrier loss
;
; End Function Key routines
;
endfun: xra a ; No character entered
ret
;
if chatf
;
; Bye's Chat Mode
;
bychat:
call conin ; pitch out the ^Q
call prtsta
db 46,'Chat',0
call prinpl
dc 'Chat',cr,lf
bycha2: call conin ; end on control c
cpi 'C'-'@'
jrz bycha3
bycha1: push psw
push h
push b
mov c,a
call conout
pop b
pop h
pop psw
push psw
bit 7,m
cz mconout ; print it to modem if not enabled
pop psw
cpi 'M'-'@'
jrnz bycha2 ; Loop if not a carriage return
mvi a,'J'-'@'
jr bycha1 ; And append linefeed if there
bycha3:
call prinpl
dc 'End Chat',cr,lf
call prtsta
db 46,,4
jmp endfun
;
endif ; chatf
;
exit:
z3ret equ $+1 ; point to code to modify
jmp $-$ ; ZCPR's return address
;
prinlc: lda bymode ; Get current Mode
sta pritmp ; Save it
res 7,a ; turn off modem IO
setb 6,a ; turn on lcl IO
sta bymode
xtix ; print the string
call print
xtix
lda pritmp ; restore mode
sta bymode
ret
pritmp: db 0
;
prinpl: xtix ; Get string starting address
call print ; Print it
xtix ; Since we're pointing to next code location
ret ; Go there!
;
prinlo: xtix ; Get string starting address
call print ; Print it
; call delay ; My modem is too d**n slow
xtix ; Since we're pointing to next code location
ret ; Go there!
;
print: ldx a,0 ; Get next char
bit 7,a ; Check for Carry
push psw
res 7,a ; Mask Carry Bit
mov c,a
call conout ; Print it
inxix ; point to next char
pop psw
rnz
jr print
;
;
;.1 sec delay routine
;
delay: push b
lxi b,4167*(mhz/10)+417*(mhz mod 10) ; constant * MHz10x
;
delay1: dcx b
mov a,b
ora c
jrnz delay1
pop b
ret
;
;.001 sec delay routine
;
sdelay: push b
lxi b,42*(mhz/10)+4*(mhz mod 10) ; constant * MHz10x
jr delay1
;
; Long delay routine, B contains # of .1 sec delays
;
ldelay: call delay
dcr b
jrnz ldelay
ret
;
newbio: lhld bios+1 ; Point to bios start
mvi l,0
lxi d,tolst ; Point to storage table
lxi b,tolen-tolst ; table length
ldir ; Save old jump table
lxi h,tnlst ; Point to new jump table
lded bios+1
mvi e,0
lxi b,tnlen-tnlst
ldir ; We are now running under BYE
ret
;
oldbio: lxi h,tolst ; Put things back the way they were
lded bios+1
mvi e,0
lxi b,tolen-tolst
ldir
ret
;
tolst:
ocboot: jmp 0
owboot: jmp 0 ; This will hold the BIOS routines
oconst: jmp 0 ; BYE will modify
oconin: jmp 0
oconout: jmp 0
olist: jmp 0
opunch: jmp 0
oreader: jmp 0
tolen:
;
tnlst:
cboot:
if obye ; Emulate Old BYE?
jmp fakeit
else
jmp 0
endif
wboot: jmp owboot ; Here is the new jump table
const: jmp bconst
conin: jmp bconin
conout: jmp bconout
if lstdev ; retain printer for sysop?
list: jmp whlst
else
list: jmp mconout
endif ; lstdev
punch: jmp bconout
reader: jmp bconin
tnlen:
;
; Structure to look like the old byes
;
if obye
fakeit: ds 15
dw oconout
db 'BYE'
endif
;
; Routines patched in by BYE
;
bconst:
if z3whl
lda z3whl
lxi h,owheel ; check for wheel change
cmp m
jrz bcst3
sta owheel
ora a ; wheel set?
cz usrdru ; then set remote dru
cnz sysdru ; else set sysop dru
endif ;z3whl
bcst3: lxi h,bymode ; local console enabled?
bit 6,m
jrz bcst1 ; nope, don't check
push h ; used later
if lclans
bit 1,m ; In local mode ?
cnz chkcal ; check for a caller
endif ; lclans
lda lchar ; got an uneaten one?
ora a
jrnz bcst2 ; Yup, still have it
call oconst ; check con status
ora a
pop h
sta lchar ; flag local char
sta lclst
jrz bcst1 ; no char
push h
call oconin ; get local char
call fkeys ; check and process local function keys
bcst2: pop h
sta lchar ; store away char
ora a ; make flags follow a
ret
;
bcst1: bit 7,m ; Modem enabled?
rz ; Nope, don't bother
;
if kilcalr ; Kill caller if loc 0 <> jump
lda 0
cpi jump
jnz kilcal ; Kill him if instructed by higher program
endif ; kilcalr
;
call carok ; Check for carrier
jz clrou ; Fool dropped carrier on us
call mdinst ; Check for modem status
rnz ; Everything's hunkey dory
;
if timeout
push h
lxi h,bymode
bit 5,m ; Paying attention to carrier
jrnz ndata
lxi h,tocnt ;No data, incr. timeout counter
inr m
jrnz ndata ;don't timeout yet
inx h
inr m ;next byte of counter
jrnz ndata
lxi h,toval ;1 "minute", no data
dcr m
jrnz ndata ;still not timed out...
jmp timout ;finally... timed out...
;
ndata:
xra a ;no character for sure
pop h
endif ; Timeout
;
ret
;
toval: ds 1
tocnt: ds 2
lchar: db 0
owheel: db 0
;
bconin: call bconst ; Wait for char avail
ora a
jrz bconin
;
if timeout
xra a ; Clear timeout
sta tocnt
sta tocnt+1
mvi a,tmins
sta toval
endif ;timeout
;
lxi h,bymode ; local con enabled?
bit 6,m
jrz bcin1 ; Nope, skip
lda lchar ; Get local status
ora a
jrz bcin1 ; it was not local
push psw
xra a ; clear local character
sta lchar ; hit.
pop psw
ret
bcin1: jmp mdinp
;
bconout:
lxi h,bymode ; local con enabled?
bit 7,m ; remote con enabled?
jrz bcou1 ; nope, skip
push h
push b ; in case of trashed char
call carok ; Check for carrier
jz clrou ; Fool dropped carrier on us
call mconout
pop b
pop h
;
bcou1: bit 6,m
rz ; nope, done
call oconout ; print it
ret
;
if lstdev
;
; Wheel check for List Device
;
whlst: sta wlst ; better to be safe than sorry.
lda z3whl
ora a ; is wheel set?
lda wlst
jz mconout ; nope, hope they like double characters.
jmp olist ; let's hope there's a printer out there.
;
wlst: ds 1
endif ; lstdev
;
; Modem Conout routine
;
mconout:
call mdoutst
jrz mconout ; wait till we can do it
mov a,c
call mdoutp ; do it
ret
;
;---------------- Modem dependent routines start here ----------------------
;
; This should really be done as two entirely independent overlays -
; one for smart (Hayes compatible) modems and one for dumb. Then there
; would be no need for the if-else-endif.
;
if not dumb ; smart "Hayes" modem
modans0 call conin ; wait for a character
mov b,a
lda lclst
ora a ; Was it a local char?
mov a,b
rnz ; yes - return with nz flag
lxi h,bymode ; We're probably going to set a mode soon
cpi '2' ; Is it a RING?
jrz mdans1
cpi '1' ; How 'bout connect 300?
jrz mdans3
cpi '5' ; connect 1200?
jrz mdans4
cpi '3' ; No Carrier
jrnz modans0
if etb
xra a ; set z flag
sta carion ; assume carrier on
endif
ret
;
mdans1: res 6,m ; turn off local console
push h
call prinlo
db 'ATA',cr+80h ; answer the phone
pop h
setb 6,m ; turn on local console
jr modans0
mdans3: call set300
jrnz mdans7
jr mdans5
mdans4: call set1200
jrnz mdans7
mdans5: call delay
res 5,m ; Carrier enabled
if etb
mvi a,0ffh
sta carion ; mark 'carrier on'
; If hardware carrier detect is available leave this in else remove it
mvi b,10 ; Check carrier for 1.0 seconds
mdans6: call carok
jrz mdans7
call delay
djnz mdans6
endif ; etb
ret
mdans7: lxi h,bymode
call nxtcal
setb 5,m
xra a
ret
;
sync: lxi h,bymode
setb 7,m
setb 5,m ; ignore carrier
setb 6,m ; turn dual io on
ret
;
; check for incoming call
;
incmcl: call bconst ; char avail from modem?
rz ; nope, continue
incmcl1 call bconin ; Get modem char
cpi '2' ; RING?
jrz incmcl2
xra a ; set z flag
ret
incmcl2 lxi h,bymode
setb 1,m
call mdans1 ; Answer the phone
ori 0ffh ; set nz flag
ret
;.............. this is the dumb modem overlay .....................
else ; dumb modem
modans0 call const
jrz mdansC ; got a character?
call conin
mov b,a
lda lclst
ora a ; Was it a local char?
mov a,b
rnz ; yes
mdansC call mdcarck ; someone here?
jrz modans0 ; if so, set baud
mdans8: mvi b,5 ; five tries to get baud right
lxi h,bymode
setb 6,m ; enable console IO
setb 7,m ; enable modem IO
mdans9: call mdcarck ; did they drop carrier?
rz
;
push b ; save 'em
call set300 ; try 300 baud
call conin
pop b
cpi cr ; did we get a CR?
rz
;
push b
call set1200 ; try 1200 baud
call conin
pop b
cpi cr ; did we get a CR?
rz
;
djnz mdans9
call nxtcal ; somethings confused, hang up on 'em
xra a ; set z flag
ret
;
sync: ret ; just return if dumb modem
;
incmcl: ; check for incoming call
call mdcarck ; someone on the line?
rz ; nope
call mdans8 ; set up for dumb remote caller
ori 0ffh ; set nz flag
ret
endif ; dumb
;
; If you can put the phone on-hook and off-hook via the UART then this
; label and appropriate code should be in the UART overlay.
;
; The following code uses "smart" modem capabilities to compensate for
; the fact that my UART is so dumb. ETB
;
mdansw
lxi h,bymode ; save bymode
mov a,m
push psw
setb 7,m ; modem on
res 6,m ; console off
setb 5,m
mvi b,15
call ldelay ; wait 1.5 sec before +++
call prinlo
db '++','+'+80h ; switch modem to command mode
mvi b,15
call ldelay ; wait 1.5 sec after +++
call prinlo
db 'ATH',cr+80h ; hang up phone
call l2char ; get echo (if any)
call l2char ; get status
if etb
lxi h,carion
mvi m,0 ; set 'carrier off'
endif
lxi h,bymode
pop psw ; restore bymode
mov m,a
ret
;
; .................................................................
;
getc: lxi b,80*mhz ; nr times to try
; to get char from modem
; the nr of times to try is sensitive to the speed of the const function
; if zbye won't get started try raising the 80 to 160 or more. The only
; adverse effect should be to slow the program down some.
getc3 push b
call const ; check status
pop b
ora a
jrnz getc2 ; char avail?
dcx b ; no - count tries
mov a,b
ora c
jrnz getc3 ; try again?
stc ; i'm exhausted, lets quit
ret
getc2 call conin ; get the character
ora a ; clear carry
ret
;
; get characters from modem till it times out then test the last 2 chars
; to see if they are '0' and car ret.
;
l2char lxi h,0 ; get last 2 chars from modem
l2c2 push h
call getc
pop h
jrc l2c1 ; no chars left
mov h,l
mov l,a
jr l2c2
l2c1
mov a,h
cpi '0'
rnz
mov a,l
cpi cr
ret
;
;------------------- Start of UART dependent routines ------------------
;
; the following code is specific for ETB's modem port and would have
; to be extensively modified for anyone else.
;
dport equ 0e3f8h ; modem data port
sport equ dport+1 ; modem status port
;
dav equ 4 ; data available bit
tbmt equ 8 ; transmit bufr empty bit
err equ 13h ; overrun, framing, and parity error bits
;
; This routine is supposed to "turn off everyting on the modem, hang it up,
; and get it ready to wait for a RING. (DTR off)" but most of this is
; either impossible or undesireable on mys system. ETB
;
mdinit ; initialize port
lda dport ; discard existing data
ret
;
set300: ; 300 baud not supported
ori 0ffh
ret
;
set1200 ; set 1200 baud
ora a
ret
;
; The following uses software 'carrier detect' because ETB's system
; does not provide hardware carrier detect.
;
mdcarck
lda carion ; is carrier on?
ora a
ret
carion db 0ffh ; software 'carrier on' switch
;
mdinst ; modem input status
lda sport
cma ; invert bits
mov b,a ; save status
ani dav ; data available?
rz ; no
mov a,b ; get stat back
ani err ; check for errors
jrz mdinst1 ; noerror
lda dport ; discard data
xra a ; clear status
ret
mdinst1 ori 0ffh ; data avail
ret
;
mdinp ; modem input
lda dport ; get data
cma ; invert bits
ani 7fh ; delete hi bit
ret
;
mdoutst ; modem output status
lda sport ; get status
cma ; invert bits
ani tbmt ; buffer empty?
ret
;
mdoutp ; modem output
cma ; invert bits
sta dport ; send data
ret
;
;----------------- Start of Terminal dependent routines-------------------
;
; There are essentially 3 options available for printing status info on
; the local console;
;
; 1) print it on the "25th line" where it will not scroll. This is obtained
; by setting "statln equ yes" and then seeing to it that the code below
; corresponds to your particular terminal configuration.
;
; 2) print it just like any other info and let it scroll. This is obtained
; by setting "statln equ no". This option makes absolutely no unusual
; demands on the terminal and should run on any system.
;
; 3) don't print it at all. This is obtained by converting the subroutine
; prtsta into a dummy (ret instruction). If desired you may then discard
; most if not all of this overlay.
;
; These macros indicate the characters sequences to cause the specified
; action on a specific terminal. You will probably have to change the
; data below if you wish to use "line 25".
;
if statln
curpos macro x,y,last ; Position Cursor to X,Y (0 offset)
db 1bh,'=',' '+y,' '+x+(80h and last)
endm
;
enab25 macro last ; Enable 25th line
db 1bh,'C','7'+(80h and last)
endm
;
disab25 macro last ; Disable 25th line
db 1bh,'B','7'+(80h and last)
endm
;
pucu macro last ; Push cursor
db 1bh,'B','6'+(80h and last)
endm
;
pocu macro last ; Pop cursor
db 1bh,'C','6'+(80h and last)
endm
;
cls macro last ; Clear Screen
db 1ah+(80h and last)
endm
;
curof macro last ; Cursor off
db 1bh,'C','4'+(80h and last)
endm
;
curon macro last ; Cursor on
db 1bh,'B','4'+(80h and last)
endm
endif ; statln
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;
; Print status information on the local terminal. The calling sequence
; is call prtsta
; db m,string,n
; where m is the column number on the screen where string is to be printed
; followed by n blanks.
;
prtsta:
; ret ; to turn off all status reports
; activate this ret instruction
xthl
mov a,m ; get ptr to column
inx h
xthl
if statln ; fancy terminal
adi ' '+80h
sta prtstax
call prinlc
enab25 no ; enable line 25
pucu no ; push cursor
curpos 0,24,yes ; move cursor
prtstax equ $-1
else ; plain terminal
mov b,a
ora a ; column 0?
cnz tab ; print blanks til col is reached
endif ; statln
;
xthl ; point to string
prtstas mov a,m ; get next char in string
inx h ; increment ptr
cpi 32 ; end of string?
jrc prtsta2
mov c,a
push h
call oconout ; print char on console
pop h
jr prtstas
prtsta2 xthl ; return adr
mov b,a ; nr blanks to print
ora a
cnz tab ; print them
;
if statln
call no25
else
call prinlc
dc cr,lf
endif ;statln
ret
;
go25:
if statln
call prinlc
enab25 no ; enable 25th line
pucu yes ; push cursor
endif ; statln
ret
;
no25:
if statln
call prinlc
pocu no ; pop cursor
disab25 yes ; disable 25th line
endif ; statln
ret
;
cursoff:
if statln
call prinlc
curoff yes ; cursor off
endif ; statln
ret
;
curson:
if statln
call prinlc
curon yes ; cursor on
endif ; statln
ret
;
clrscr:
if statln
call prinlc ; clear screen
cls yes
endif ; statln
ret
;
; Print (on local console) number of spaces contained in B register.
;
tab:
push b
mvi c,' '
call oconout
pop b
djnz tab
ret
;
;-------------------- End of terminal dependent routines ---------------------
;
; .z80
;
; if2 ; this is turned off because I use a one pass assembler ETB
if $ ge (rcp+rcps*128)
.printx ->This RCP is too large, don't try to run it.<-
endif
; endif
;
.dephase
byend:
end
cp+rcps*128)
.