home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
packet
/
rli120.ark
/
CHARIO.MAC
< prev
next >
Wrap
Text File
|
1987-01-17
|
13KB
|
732 lines
; CHARIO.MAC - 1/17/87 - Character I/O
.z80
maclib TNC.LIB
entry addcr0,mcmt,getdat,getwt,cmd,cmdlen,cmdtyp
entry const,conin,conot
entry blink,dtime,itime,@inch,@outch,@prtx
entry conmod,dis,gotreq,gotcon,gotlnk,lnkst,discon,prtcmd
entry erdone,mdone,erfind,mfind,erprot,mprot
entry ercant,mcant,ername,mname,ertime,mtime
entry erexst,mexst,erwhat,mwhat
entry eofs,leofs,@outn,@outnb,pgst,pghd,pgck,pgdn
entry lm3,waitc,pause,cmdtnc,@docmd,wtcmd,tnca,tncb
external short,mode,prtpar,btchm,uccnt,ucalls
external mcall,scall,ocall,rcall,mtnc,stnc
external mhnr,mhdate,mhtime,mhto,mhfrom,mhbbs
external bindec,numb,@cmp,@cmpcmd,movcal,@cmp,@wait
external date,time,mnr,mcnt,usname,usdate,ustime,usmnr
external ncerrs
asciictl
tncdefs
timdef
outn macro adr,ct
if not nul adr
ld hl,adr
endif
if not nul ct
ld b,ct
endif
call @outn
endm
outnb macro adr,ct
if not nul adr
ld hl,adr
endif
if not nul ct
ld b,ct
endif
call @outnb
endm
; BIOS linker.
cseg
blink: ld hl,(1)
inc hl
inc hl
inc hl
ld de,const
ld bc,9
ldir
ret
; Copy of the BIOS console jumps.
dseg
const: jp $-$
conin: jp $-$
conot: jp $-$
; Error/status messages.
mdone: ds 2
mfind: ds 2
mprot: ds 2
mcant: ds 2
mname: ds 2
mtime: ds 2
mexst: ds 2
mwhat: ds 2
cseg
erdone: prtx mdone
jr waitc
erfind: prtx mfind
jr waitc
erprot: prtx mprot
jr waitc
ercant: prtx mcant
jr waitce
ername: prtx mname
jr waitc
ertime: prtx mtime
jr waitc
erexst: prtx mexst
jr waitc
erwhat: prtx mwhat
jr waitce
addcr0: ld (hl),cr
inc hl
ld (hl),0
ret
; Make TNC on PRINTER port master.
tnca: ld a,rbiob
ld (stnc),a
ld a,raiob
ld (mtnc),a
ld (iobyte),a
ret
; Make TNC on PRINTER port master.
tncb: ld a,raiob
ld (stnc),a
ld a,rbiob
ld (mtnc),a
ld (iobyte),a
ret
; If local user, do xon/xoff pause.
; If local user and long menu, wait for keypress.
dseg
lm3: ds 2
cseg
waitce: ld hl, ncerrs
inc (hl) ; Count command errors
waitc: cmpm mode,lmode
ret nz ; Not local, no wait
cmpm short,true
ret z ; Short local menu, no wait
prtx lm3
jp @inch
pause: cmpm iobyte,ciob
ret nz
call const
ret z
call @inch
ld a,c
cp dc3
ret nz
call @inch
ret
; Screen paging routines.
dseg
lnmax: ds 1
lncnt: ds 1
pghdr: ds 2
cseg
pgst: ld (pghdr),hl ; Save address of header
ld a,l
or h ; Is a header?
ld a,23 ; Page with no header
jr z,pgsta ; No
ld a,22 ; One less line
pgsta: ld (lnmax),a ; Save max
ld (lncnt),a ; Init count
ret
pghd: ld hl,lncnt ; Line we on
ld a,(lnmax) ; Lines on screen
cp (hl) ; At top?
ret nz ; No
dtz pghdr ; Is a header?
ret z ; No
jp @prtx ; Print header
pgck: ld hl,lncnt ; Point to line count
dec (hl) ; Count line
ret nz ; More lines
ld a,(lnmax)
ld (hl),a ; Reset counter
jr pgpaus ; Pause
pgdn: ld a,(lncnt) ; Current line
ld hl,lnmax ; Lines on screen
cp (hl) ; We paused already?
ret z ; Yes
pgpaus: cmpm iobyte,ciob ; Local user?
ret nz ; No
prtx lm3 ; Print "Any key to continue"
call @inch ; Wait for keypress
push bc ; Save response
ld c,cr ; Give a CR
call @outch
pop bc
retz ; Zero set, got char
; Print the command line.
prtcmd: ld a,(cmdlen)
or a
jr z,prcme
ld b,a
ld hl,cmd
prcma: ld c,(hl)
call @outch
inc hl
dec b
jr nz,prcma
prcme: ld c,cr
call @outch
ret
; Output (B) charcters at (HL).
@outn: ld c,(hl)
call @outch
inc hl
dec b
jr nz,@outn
ret
; Output (B) characters at (HL), except blanks.
@outnb: ld a,(hl)
cp ' '
jr z,outnba
ld c,a
call @outch
outnba: inc hl
dec b
jr nz,@outnb
ret
; Do a command or string of commands at (HL).
dseg
docmdc: ds 2
cseg
@docmd: ld (docmdc),hl
xor a ; Get a zero
cp (hl) ; Zero in string?
ret z ; Yes, all done
ld a,cr ; Get a CR
docmda: cp (hl) ; One in string?
inc hl ; Point to next char
jr nz,docmda ; Not CR, keep looking
ld c,(hl) ; Save char after CR
ld (hl),0 ; Put 0 after CR
push hl ; Save pointer into string
push bc ; Save char after CR
ld hl,(docmdc) ; Point to start of command
call @prtx ; Send it to tnc
call wtcmd ; Wait for cmd: from tnc
pop bc ; Get char after CR back
pop hl ; Get string pointer back
ld (hl),c ; Put char after CR back
jr @docmd ; Do next command
wccmd: db 'cmd:'
; Get TNC to command state.
cmdtnc: ld c,etx
call @outch
; Wait for TNC to respond to a command.
; Return in A: 0=ok, 1=timeout, 2=command no good.
wtcmd: lxim timer,3 ; 3 second wait.
ld b,0 ; Assume good status
wca: ld de,wccmd
wcb: dtz timer
jr z,wcd ; TNC did not respond.
call const
jr z,wcb
call @inch
ld a,(de)
cp c
jr nz,wcc
; Looking for cmd:
cp ':'
jr z,wce
inc de
jr wcb
wcc: ld a,c
cp '?'
jr nz,wca
ld b,2 ; Got EH?
jr wca ; Now look for "cmd:"
wcd: ld b,1 ; Timeout
wce: ld a,b ; Return status in A
or a ; Set flags
ret
; Character input.
; Character from current console device returned in C.
; Echoed to local console if from a tnc.
@inch: push hl
call conin
pop hl
ld c,a
ld a,(iobyte)
cp ciob ; Console?
ret z ; Yes, no echo
jr echo
; Character output.
; Character in C output to current console device.
; Echoed to the local console if current device is a tnc.
; Assumes all registers preserved except PSW
dseg
ctnc: ds 1
cseg
@outch: cmpm iobyte,ciob
jr z,@co
call conot
echo: ld a,c
cp ff
ret z ; No clear screen from tnc
movb ctnc,iobyte
mvim iobyte,ciob
call @co
movb iobyte,ctnc
ret
; Output (C) to local console.
@co: ld a,c
cp lf
ret z ; Ignore LF, is added after CR.
call conot
ld a,c
cp cr
ret nz
ld c,lf
call conot
ld c,cr
ret
; Print a string. Expand "variable text" fields.
dseg
pxpt: ds 2
pxst: ds 2
cseg
pxtbl: dw pxa,pxb,pxc,pxd,pxe,pxf,pxg,pxh,pxi,pxj,pxk,pxl,pxm
dw pxn,pxo,pxp,pxq,pxr,pxs,pxt,pxu,pxv,pxw,pxx,pxy,pxz
@prtx: ld (pxst),hl
prtxa: ld (pxpt),hl
ld a,(hl)
or a
ret z ; NUL ends string
cp '$' ; Is it a $ ?
jr nz,pxok ; No, print it
inc hl ; Yes, point to char after $
ld a,(hl) ; Get char after $
cp 'A'
jr c,px1 ; Not within A-Z, print $ and char
cp 'Z'+1
jr nc,px1 ; Not within A-Z, print $ and char
sub 'A' ; To make index into table
ld l,a
ld h,0
add hl,hl ; Double it, table is word items
ld de,pxtbl ; Point to start of table
add hl,de ; Add twice index to get to item
ld e,(hl) ; Low byte of sub addr
inc hl
ld d,(hl) ; Hi byte of sub addr
ex de,hl
jp (hl) ; Go do it
px1: ld a,'$' ; Print the $
pxok: ld c,a
call @outch
ld hl,(pxpt)
inc hl
jr prtxa
pxa: outnb mhbbs,6
jp pxnxt
; Insert bell
pxb: ld c,bell
call @outch
jp pxnxt
pxc: ld hl,(mnr)
jp pxnum
pxd: outn date,6
jp pxnxt
; Insert calls with unread mail
pxe: ld hl,(pxpt)
ld de,(pxst)
or a ; Clear carry
sbc hl,de
ld a,btchm
sub l
ld e,a ; Max chars to print
ld hl,uccnt
ld d,(hl)
ld hl,(ucalls)
pxeg: ld a,(hl)
and 80h ; Is call a bbs?
jr nz,pxej ; Yes, dont put in beacon
ld b,6
push hl
pxeh: ld a,(hl)
cp ' '
jr z,pxei
ld c,a
call @outch
inc hl
dec e
dec b
jr nz,pxeh
pxei: pop hl
dec e
ld a,e
sub 8
jp c,pxnxt ; No more room
ld c,' '
call @outch
pxej: push de
ld de,6
add hl,de
pop de
dec d ; Any more calls in list?
jr nz,pxeg ; Yes
jp pxnxt
; Insert form feed
pxf: ld c,ff
call @outch
jp pxnxt
pxg: outnb mhto,6
jp pxnxt
; Pass (ignore) the cr
pxh: inxm pxpt
jp pxnxt
pxi: outnb usname,12
jp pxnxt
pxj: outn mhdate,6
jp pxnxt
pxk: outn mhtime,4
jr pxnxt
pxl: ld hl,(mnr)
dec hl
jr pxnum
pxm: ld hl,(mhnr)
jr pxnum
pxn: ld hl,(mcnt)
jr pxnum
pxo: outnb ocall,6
jr pxnxt
pxp: outnb mhfrom,6
jr pxnxt
pxr: outnb rcall,6
jr pxnxt
pxs: outnb scall,6
jr pxnxt
pxt: outn time,4
jr pxnxt
pxu: outnb mcall,6
jr pxnxt
; Print changable param values.
pxv: call prtpar
jr pxnxt
; Insert syn
pxw: ld c,syn
call @outch
jr pxnxt
pxx: outn usdate,6
jr pxnxt
pxy: outn ustime,4
jr pxnxt
pxz: ld hl,(usmnr)
; Print the number in (HL)
pxnum: call bindec
; Print the previously converted number.
pxq: outnb numb,5
; Move on to the next character
pxnxt: ld hl,(pxpt)
inc hl
inc hl
jp prtxa
; Get a line from the console.
dseg
dtime: ds 2 ; Wait time for disconnect
itime: ds 2 ; Timeout waiting for CR
otimer: ds 2 ; Save / restore timer value
gotreq: ds 1 ; True if got connect request
cmdlen: ds 1 ; # chars in buffer
cmd: ds cmdmax
cmdtyp: ds 1
cseg
eofs: db '*** EOF'
leofs equ $-eofs
conv: db 'CONV',cr,0
cst: db 'C',cr,0
cd: db 'D',cr,0
concmd: db '*** CONNECTED to '
lconcmd equ $-concmd
discmd: db '*** DISCONNECTED'
ldiscmd equ $-discmd
reqcmd: db '*** connect request:'
lreqcmd equ $-reqcmd
lnkcmd: db '*** LINKED to '
llnkcmd equ $-lnkcmd
stat:
isdis: db 'Link state is:'
lstat equ $-stat
db ' DISCONNECTED'
lisdis equ $-isdis
discon: cmpcmd isdis,lisdis
ret
; Get tnc to converse mode
conmod: ld hl,conv
call @prtx
wait convtim
ret
; Find out the link state.
lnkst: ld hl,cst
call @prtx ; Send "C" to tnc
lnksta: mvim getwt,false ; Don't wait after con req
call getdat
ckcmd lnksta,lnkstc,lnkstb
cmpcmd stat,lstat
jr nz,lnksta
lnkstb: call wtcmd ; Eat the cmd: after the C
ret
lnkstc: call wtcmd ; Eat the cmd: after the discon
jr lnksta
; Return zero set if cmd contains a connect.
gotcon: cmpcmd concmd,lconcmd
ret nz
ld c,lconcmd
jr mcmt
; Return zero set if cmd contains a link.
gotlnk: cmpcmd lnkcmd,llnkcmd
ret nz
ld c,llnkcmd
jr mcmt
; Disconnect
dis: call cmdtnc ; Make sure tnc in command mode
call lnkst ; Get link state
call discon ; We connected?
ret z ; No
disa: ld hl,cd
call @docmd ; Do the disconnect
movw timer,dtime ; Start timer
disb: call const ; Char from TNC?
jr nz,disc ; Yes
dtz timer ; No, timed out?
jr z,dis ; Yes, disconnect RIGHT NOW
jr disb ; Wait some more
disc: mvim getwt,false ; No wait if con req
call getdat ; Get line from TNC
ckcmd disb,disd,disa
jr disb ; Not disconnected yet
disd: call wtcmd ; Disconnected.
ret
; Move command tail to front of cmd buffer.
; (C) = first char in tail.
mcmt: ld b,0
ld hl,cmd
add hl,bc
ld a,(cmdlen)
sub c
ld (cmdlen),a
ret z ; No call...
ld c,a
ld de,cmd
ldir
xor a
ret ; With zero set
dseg
getwt: ds 1
cseg
getdat: movw otimer,timer ; Save countdown timer
movw timer,itime
mvim cmdtyp,cdata
gtdta: xor a
ld (cmdlen),a
ld b,cmdmax
ld de,cmd
gtdtb: call const
jr nz,gtdtc
cmpm iobyte,ciob
jr z,gtdtc
dtz timer
jr nz,gtdtb
mvim cmdtyp,ctimcmd
jp gtdtz
gtdtc: call @inch
ld a,c
cp del
jr z,gtdtbs ; Treat DEL like BS
cp ' '
jr nc,gtdte ; Not CTL char
cp cr
jr z,gtdtcr
cp lf
jr z,gtdtlf
cp bs
jr z,gtdtbs
cp ff
jr z,gtdte
cp bell
jr z,gtdte
cp tab
jr z,gtdte
cp eof ; ^Z
jr z,gtdte
cp linkcmd ; ^W
jr z,gtdte
jr gtdtb ; Ignore control char
; Char is line feed.
gtdtlf: ld a,(cmdlen)
or a
ld a,c
jr nz,gtdtb ; LF in middle of line, ignore
jr gtdty ; Initial LF, treat as no data rcvd
; Char is backspace.
gtdtbs: ld hl,cmdlen
ld a,(hl)
or a
jr z,gtdtb ; Don't backspace beyond start of line
dec (hl) ; One less char in buffer
inc b ; Room for one more char in buffer
dec de ; Move buffer pointer back
cmpm iobyte,ciob ; Local console typing?
jr nz,gtdtb ; No, get next char
call @outch ; Echo BS SP BS
ld c,' '
call @outch
ld c,bs
call @outch
jp gtdtb
; Char is ok, put in buffer
gtdte: ld (de),a ; Stick char in buffer
inc de ; Point to next buffer location
ld hl,cmdlen
inc (hl) ; Count the char
cmpm iobyte,ciob ; Local console typing?
call z,@outch ; Echo char to local console
dec b ; Count the room in buffer
jp nz,gtdtb ; Room for more char, get one
jr xx ; Ran out of buffer
; Got CR, echo it if local console.
gtdtcr: cmpm iobyte,ciob
call z,@outch
; Is it *** DISCONNECTED?
xx: cmpcmd discmd,ldiscmd
jr nz,gtdtg
mvim cmdtyp,cdiscmd
jr gtdtz
; Is it *** connect request ?
gtdtg: cmpcmd reqcmd,lreqcmd
jr nz,gtdtz
ld de,rcall
ld hl,cmd+lreqcmd
ld a,(cmdlen)
sub lreqcmd
call movcal ; Save call on con req
mvim gotreq,true
cmpm getwt,true
jp z,gtdta
gtdty: mvim cmdtyp,cnull
gtdtz: movw timer,otimer ; Restore timer count
mvim getwt,true
ld a,(cmdtyp)
ret
end