.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 ; to . ; ; 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) .