903 lines
18 KiB
Plaintext
903 lines
18 KiB
Plaintext
; qterm.z - patch area and main control loop for qterm
|
||
|
||
.incl "c:vars"
|
||
.incl "c:version"
|
||
|
||
.var escchr '\\' & 0x1f
|
||
.var biosjp 1
|
||
.var memtop 6
|
||
|
||
.macro table byte,addr
|
||
dw addr
|
||
db byte
|
||
.endm
|
||
|
||
jp start ; skip over the patch area
|
||
|
||
; now for the screen access routines - these are put here because moveto
|
||
; will have to access scrout, and this provides a ready access point
|
||
|
||
#kbdsts:
|
||
jp 6 ; keyboard status routine
|
||
#kbdin:
|
||
jp 9 ; keyboard input routine
|
||
#scrout:
|
||
jp 12 ; screen output
|
||
jp decoj ; access to decimal output routine
|
||
|
||
; These bits are system dependant, and are put at the beginning of the
|
||
; program so that them as what needs to change them, can.
|
||
|
||
; modist - return with z flag clear iff there is a char waiting at modem port
|
||
|
||
.org 0x0010
|
||
#modist:
|
||
ld hl,(_base_)
|
||
ld a,(hl)
|
||
inc hl
|
||
xor (hl)
|
||
ret
|
||
|
||
; modin - read char from modem port: modist has been used to check it's there
|
||
|
||
.org 0x0020
|
||
#modin:
|
||
ld hl,(_base_)
|
||
inc (hl)
|
||
res 5,(hl)
|
||
ld e,(hl)
|
||
inc hl
|
||
inc hl
|
||
ld d,0
|
||
add hl,de
|
||
ld a,(hl)
|
||
ret
|
||
|
||
; modost - return with z flag clear iff the modem can accept another char
|
||
|
||
.org 0x0030
|
||
#modost:
|
||
in a,(0x2e)
|
||
and 0x80
|
||
ret
|
||
|
||
; modout - send char to modem port
|
||
|
||
.org 0x0040
|
||
#modout:
|
||
out (0x2f),a
|
||
ret
|
||
|
||
; sbreak - start a break condition on line
|
||
|
||
.org 0x0050
|
||
#sbreak:
|
||
ld a,0x0d
|
||
out (0x2e),a
|
||
ret
|
||
|
||
; ebreak - terminate break condition
|
||
|
||
.org 0x0060
|
||
#ebreak:
|
||
ld a,0x05
|
||
out (0x2e),a
|
||
ret
|
||
|
||
; dtroff - disable dtr to cause modem to hang up
|
||
|
||
.org 0x0070
|
||
.extern #dtroff ; external so hangup can work
|
||
#dtroff:
|
||
ld a,0x24
|
||
out (0x21),a
|
||
ret
|
||
|
||
; dtron - re-enable dtr
|
||
|
||
.org 0x0080
|
||
#dtron:
|
||
xor a
|
||
out (0x21),a
|
||
ret
|
||
|
||
; setbd - take byte in a from baud table, use it to set baud rate
|
||
|
||
.org 0x0090
|
||
#setbd:
|
||
out (0x2b),a
|
||
ret
|
||
|
||
; these next eight are byte pairs - the first byte is used by setbd above.
|
||
; the second is a -1 for an active baud rate entry, and a 0 for inactive
|
||
|
||
.org 0x00a0
|
||
.extern b38400
|
||
b38400: db 0,no
|
||
.extern b19200
|
||
b19200: db 0,no
|
||
.extern b9600
|
||
b9600: db 1,yes
|
||
.extern b4800
|
||
b4800: db 2,yes
|
||
.extern b2400
|
||
b2400: db 4,yes
|
||
.extern b1200
|
||
b1200: db 8,yes
|
||
.extern b600
|
||
b600: db 16,yes
|
||
.extern b300
|
||
b300: db 32,yes
|
||
|
||
; setmod - take a byte from the mode table, use it to set the uart mode
|
||
|
||
.org 0x00b0
|
||
#setmod:
|
||
out (0x2c),a
|
||
ret
|
||
|
||
; now the twelve mode bytes for setting comm format
|
||
|
||
.org 0x00c0
|
||
.extern modtab
|
||
modtab:
|
||
n17: db 0b10101010
|
||
n18: db 0b10001010
|
||
n27: db 0b10111010
|
||
n28: db 0b10011010
|
||
e17: db 0b10101110
|
||
e18: db 0b10001110
|
||
e27: db 0b10111110
|
||
e28: db 0b10011110
|
||
o17: db 0b10101100
|
||
o18: db 0b10001100
|
||
o27: db 0b10111100
|
||
o28: db 0b10011100
|
||
|
||
.org 0x00cc
|
||
.extern resrvd
|
||
resrvd:
|
||
db 0
|
||
|
||
; xfersz - number of K to read / write to disk during protocol transfers:
|
||
; must be 1 / 2 / 4 / 8. Generally this is best left at 8 unless you have
|
||
; a REALLY slow disk (C128 maybe) when writing / reading 8K at a time
|
||
; causes timeouts. Drop this to 4 or 2 to do disk access in smaller chunks
|
||
; to help avoid the timeout problem
|
||
|
||
.extern xfersz
|
||
xfersz: db 8
|
||
|
||
; speed - simply the cpu speed for a z80 in mhz.
|
||
|
||
.extern speed
|
||
speed: db 4
|
||
|
||
; escape - this is the character used as the escape char: since the addresses
|
||
; in the table tend to move, we just put the byte here, and then transfer
|
||
; to the table later
|
||
|
||
escape: db escchr
|
||
|
||
; the signon message - change this to be appropriate for your system
|
||
|
||
.org 0x00d0
|
||
signon: db 'Televideo TS803\0'
|
||
|
||
; now the string for clear screen
|
||
|
||
.org 0x00f0
|
||
.extern clrs
|
||
clrs: db 'z' & 0x1f, 0
|
||
|
||
; moveto - this routine is called with a word in hl - h = row &
|
||
; l = column to move to, at 109 is a routine to print a char in c,
|
||
; at 10c is a routine to print a decimal number in hl (for ansi tubes)
|
||
|
||
.org 0x0100
|
||
#moveto:
|
||
push hl ; save coords
|
||
ld c,'\e'
|
||
call #scrout ; lead in escape
|
||
ld c,'='
|
||
call #scrout ; leadin '='
|
||
pop hl
|
||
push hl
|
||
ld a,h ; row to a
|
||
call poff ; out it goes w/ offset
|
||
pop hl
|
||
ld a,l ; col to a
|
||
poff: add a,' ' ; add offset
|
||
ld c,a
|
||
jp #scrout ; & print it
|
||
|
||
; these next strings are used to do various screen functions. There are
|
||
; eight of them, and immediately preceding them is a flag byte. Each string
|
||
; has a bit in the byte, and if a capability is present, its bit should
|
||
; be set. This byte is an absolute necessity, as various programs use it
|
||
; to tell if various things are present.
|
||
|
||
.org 0x012f
|
||
.extern tcbits
|
||
tcbits:
|
||
db 0b11111111
|
||
; ||||||||
|
||
; |||||||+------ 0: bright (end highlight)
|
||
; ||||||+------- 1: dim (start highlight)
|
||
; |||||+-------- 2: delete line
|
||
; ||||+--------- 3: insert line
|
||
; |||+---------- 4: delete character
|
||
; ||+----------- 5: insert character
|
||
; |+------------ 6: clear to end of line
|
||
; +------------- 7: clear to end of screen
|
||
|
||
.org 0x0130
|
||
.extern brites
|
||
brites: db '\e(\0'
|
||
|
||
.org 0x0138
|
||
.extern dims
|
||
dims: db '\e)\0'
|
||
|
||
.org 0x0140
|
||
.extern dlstr
|
||
dlstr: db '\eR\0'
|
||
|
||
.org 0x0148
|
||
.extern ilstr
|
||
ilstr: db '\eE\0'
|
||
|
||
.org 0x0150
|
||
.extern dcstr
|
||
dcstr: db '\eW\0'
|
||
|
||
.org 0x0158
|
||
.extern icstr
|
||
icstr: db '\eQ\0'
|
||
|
||
.org 0x0160
|
||
.extern ceol
|
||
ceol: db '\eT\0'
|
||
|
||
.org 0x0168
|
||
.extern ceos
|
||
ceos: db '\eY\0'
|
||
|
||
; Entry and exit hooks. These are provided to perform custom initialisation
|
||
; on startup, and also to perform custom code on exit.
|
||
|
||
.org 0x0170
|
||
.extern entry
|
||
entry: jp do_ent
|
||
|
||
.org 0x0173
|
||
.extern exit
|
||
exit: jp do_ext
|
||
|
||
.org 0x0176
|
||
.extern #user
|
||
#user:
|
||
.if dg
|
||
jp _user_ ; go do ours
|
||
.else
|
||
ret
|
||
.endif
|
||
|
||
.org 0x0179
|
||
.extern #kbmap
|
||
#kbmap:
|
||
.if dg
|
||
jp _kbmp_ ; hook into keyboard map routine
|
||
.else
|
||
ret
|
||
.endif
|
||
|
||
.org 0x017c
|
||
_ilpr_: jp prmpjp
|
||
|
||
; finally a patch area that is provided for patching odd systems that need
|
||
; a lot of space.
|
||
|
||
.org 0x0180
|
||
|
||
do_ent:
|
||
|
||
.if dg
|
||
|
||
ld c,14
|
||
ld e,3
|
||
call 5
|
||
ld c,32
|
||
ld e,30
|
||
call 5
|
||
ld a,0b10001010 ; 8n1
|
||
out (0x2c),a
|
||
ld a,4 ; 2400
|
||
out (0x2b),a
|
||
|
||
.endif
|
||
|
||
di
|
||
ld hl,(0xff00)
|
||
xor a
|
||
ld (hl),a
|
||
ld (_base_),hl ; OK, use GSX interface area for interrupts
|
||
inc hl
|
||
ld (hl),a
|
||
ld (_here_ + 1),hl
|
||
ld de,33
|
||
add hl,de
|
||
ex de,hl
|
||
push de
|
||
ld hl,icode
|
||
ld bc,{endi - icode}
|
||
ldir
|
||
ld c,0x10
|
||
pop de
|
||
jr endit
|
||
|
||
do_ext: di
|
||
ld de,(ivec)
|
||
ld c,0
|
||
|
||
endit: ld a,i
|
||
ld h,a
|
||
ld l,0x78
|
||
ld a,(hl)
|
||
ld (hl),e
|
||
ld e,a
|
||
inc hl
|
||
ld a,(hl)
|
||
ld (hl),d
|
||
ld d,a
|
||
ld (ivec),de
|
||
ld a,0x65
|
||
out (0x28),a
|
||
ld a,c
|
||
out (0x20),a
|
||
out (0x27),a
|
||
ld a,0x64
|
||
out (0x28),a
|
||
ei
|
||
clrlp: in a,(0x2f)
|
||
in a,(0x2d)
|
||
add a,a
|
||
jr c,clrlp
|
||
ret
|
||
|
||
icode: di
|
||
push hl
|
||
push af
|
||
iclp: in a,(0x2d)
|
||
add a,a
|
||
jr nc,icdone
|
||
_here_: ld hl,0 ; filled in later
|
||
inc (hl)
|
||
res 5,(hl)
|
||
ld a,(hl)
|
||
inc hl
|
||
add a,l
|
||
ld l,a
|
||
jr nc,hok
|
||
inc h
|
||
hok: in a,(0x2f)
|
||
ld (hl),a
|
||
jr iclp
|
||
icdone: pop af
|
||
pop hl
|
||
ei
|
||
reti
|
||
endi:
|
||
|
||
ivec: dw 0
|
||
_base_: dw 0
|
||
|
||
.if dg
|
||
|
||
.var linesz 40 ; default number of chars before we start
|
||
|
||
_user_:
|
||
call _ilpr_ ; prompt for and get an answer
|
||
db 'Split? \0'
|
||
ld hl,0x7f ; point just before it
|
||
_byp: inc hl
|
||
ld a,(hl) ; get the next character
|
||
cp ' ' ; space?
|
||
jr z,_byp ; yes, skip over it
|
||
sub '0'
|
||
cp 10
|
||
jr c,_numbr ; numeric input - go handle it
|
||
add a,'0' ; convert back
|
||
or 0x20 ; force lower case
|
||
xor 0x20 ; this really tests for a null .....
|
||
jr z,_gtans ; yes, save zero byte
|
||
xor 0x20 ^ 'y' ; and check for a 'y' (including 'Y')
|
||
_gtans: ld (split),a ; save the flag - zero enables, non-zero
|
||
; disables
|
||
ld a,linesz ; set line length to default of 40
|
||
_setll: ld (linlen),a ; set the line length from a
|
||
xor a
|
||
ld (count),a ; and set the count to zero
|
||
ret
|
||
|
||
_numbr: ld e,a ; save current value in e
|
||
inc hl ; point to next character
|
||
ld a,(hl)
|
||
sub '0' ; convert .....
|
||
cp 10 ; and test if it's a digit
|
||
jr nc,_gtnum ; nope - we're all done
|
||
ld d,a
|
||
ld a,e
|
||
add a,a ; a = e * 2
|
||
add a,a ; * 4
|
||
add a,e ; * 5
|
||
add a,a ; * 10
|
||
add a,d ; + d
|
||
jr _numbr
|
||
_gtnum: xor a
|
||
ld (split),a ; else set split flag to enable
|
||
ld a,e ; and get the line length back from e
|
||
jr _setll ; go do the set with whatever we have
|
||
|
||
_kbmp_: and 0x7f ; ditch bit 7, just because I'm paranoid
|
||
_nodel: ld hl,split ; point at the flag
|
||
inc (hl)
|
||
dec (hl)
|
||
ld c,a ; save char in c
|
||
jp nz,_jstcn ; not splitting - get outa here
|
||
ld hl,(state)
|
||
ld a,h
|
||
or l ; are we in the middle of a line break?
|
||
jr nz,_linbr ; yes, so handle it elsewhere
|
||
ld a,c ; get the character back from c
|
||
ld hl,0x01cf ; point at the escape character
|
||
cp (hl)
|
||
ret z ; we have to let these through!
|
||
ld hl,count ; point hl at the count for everyone
|
||
cp '\b'
|
||
jr z,_bcksp ; handle backspaces
|
||
cp 'y' & 0x1f
|
||
jr z,_ctly ; and ^Y's
|
||
cp '\r'
|
||
jr z,_retrn ; and returns
|
||
cp '\n'
|
||
jr z,_newln ; and linefeeds
|
||
inc b ; set b to 1 for a potential swallow
|
||
cp 0x7f ; throw away deletes
|
||
ret z
|
||
cp ' ' ; is it a space?
|
||
jr z,_space ; handle specially if so
|
||
ret c ; and throw away other control characters
|
||
dec b ; reset b to pass the single character
|
||
inc (hl) ; bump count
|
||
ret ; and return - char is still in a
|
||
|
||
_bcksp: dec (hl) ; anything in the current count
|
||
inc b ; set b to 1 for a swallow
|
||
inc (hl) ; restore count
|
||
ret z ; and return if nothing there
|
||
dec (hl) ; decrement count since we're allowing it
|
||
dec b ; reset b
|
||
ret
|
||
|
||
_retrn: ld hl,retstr ; point at the return string
|
||
jr _linbr
|
||
|
||
_newln: ld hl,nlstr ; point at the new line string
|
||
jr _linbr
|
||
|
||
_ctly: ld hl,(count)
|
||
ld h,0 ; set state from count
|
||
or a
|
||
jr _setbs
|
||
|
||
_space: inc (hl) ; we passed another character, count it
|
||
ld a,(linlen) ; get the line length
|
||
cp (hl) ; too long yet?
|
||
ld a,c
|
||
dec b
|
||
ret nc ; no, return character in a
|
||
ld hl,string ; else point at the string to send
|
||
|
||
_linbr: ld a,h
|
||
or a
|
||
jr z,_sndbs ; if h is zero, send l backspaces
|
||
ld a,(hl) ; get the next character from the string
|
||
inc hl ; move the pointer
|
||
inc (hl)
|
||
dec (hl) ; end of string?
|
||
ld b,2 ; set b to 2 to say there's more coming
|
||
jr nz,_savhl ; not end of string, save hl and return
|
||
ld b,(hl) ; set b to zero again
|
||
ld hl,count
|
||
ld (hl),b ; zero out the count from b
|
||
ld h,b
|
||
ld l,b ; set hl to zero to reset the state machine
|
||
_savhl: ld (state),hl ; save the pointer / NULL
|
||
ret
|
||
|
||
_sndbs: dec l ; one less to go
|
||
_setbs: ld (state),hl ; save the state back
|
||
ld b,2 ; flag more to come
|
||
jr nz,_bok ; unless this is the last
|
||
ld b,h ; in which case b gets zero
|
||
ld (count),a ; set count to zero (a is zero from jp above)
|
||
_bok: ld a,'\b' ; stuff a backspace in a, and we're done
|
||
ret
|
||
|
||
_jstcn: ld hl,(state)
|
||
ld a,h
|
||
or l ; are we in the middle of a line break?
|
||
jr nz,_linbr ; yes, so handle it elsewhere
|
||
ld a,c
|
||
ld b,0
|
||
ld hl,count ; point hl at the count for everyone
|
||
cp '\b'
|
||
jr z,_cbksp ; count backwards
|
||
cp '\n'
|
||
jr z,_cntrt ; count return's - set to zero
|
||
cp '\r'
|
||
jr z,_cntrt
|
||
cp 'y' & 0x1f
|
||
jr z,_ctly ; handle ^Y's
|
||
cp ' '
|
||
ret c ; let control chars pass, but don't count them
|
||
inc (hl)
|
||
ret
|
||
_cntrt: ld (hl),b ; set count to zero
|
||
ret
|
||
|
||
_cbksp: dec (hl) ; anything in the current count
|
||
inc (hl)
|
||
ret z ; no, leave count alone
|
||
dec (hl) ; drop it back by one
|
||
ret ; all done
|
||
|
||
count: db 0 ; count of chars since the last new line
|
||
linlen: db linesz ; line size we're currently using
|
||
split: db 1 ; flag if we're splitting: zero => we are
|
||
state: dw 0 ; what state are we in?
|
||
|
||
string: db ' .....\r\0' ; space string to break lines
|
||
retstr: db ' [end]' ; return string to end a paragraph
|
||
nlstr: db '\r\0' ; newline to end
|
||
|
||
.endif
|
||
|
||
.org 0x0400
|
||
|
||
; put this jump here, because decout may move, so we can't have it's address
|
||
; in the patch area
|
||
|
||
decoj: jp decout
|
||
|
||
; same again: prompt may move
|
||
|
||
prmpjp: jp prompt
|
||
|
||
; now the start of the main code
|
||
|
||
start: ld sp,(memtop) ; set the stack
|
||
ld a,(biosjp + 1) ; get the bios base address
|
||
ld (#kbdsts + 2),a
|
||
ld (#kbdin + 2),a
|
||
ld (#scrout + 2),a ; fix the three jumps
|
||
call #subchk ; but now check for XSUB installed
|
||
ld a,(escape)
|
||
ld (escval),a ; set the escape character in the jump table
|
||
call setshr ; do shrink adjustment
|
||
ld a,(xfersz)
|
||
ld hl,512
|
||
sizlp: add hl,hl ; set size in K in hl
|
||
rra
|
||
jr nc,sizlp ; loop till size is set in hl
|
||
ld de,work2
|
||
add hl,de
|
||
ld (ew2p),hl ; and set pointer for transfers
|
||
ld hl,fktbl
|
||
ld de,fktbl + 1
|
||
ld bc,16 * 10 - 1
|
||
ld (hl),b
|
||
ldir ; clear fk table initially
|
||
call entry ; do the users custom code
|
||
ld sp,(memtop) ; reload the stack pointer in case things got
|
||
; bashed in the entry hook
|
||
call ilprt ; print fixed part of signon
|
||
db 'QTERM V'
|
||
version
|
||
db '\r\n'
|
||
db '(C) Copyright DPG '
|
||
year
|
||
db ' - All rights reserved\r\n'
|
||
db 'Version for \0'
|
||
call dim
|
||
ld hl,signon
|
||
call prtslp ; print the system signon message
|
||
call ilprt
|
||
db '\r\nEscape character is \0'
|
||
call dim
|
||
call presc ; remind what the escape character is
|
||
call crlf
|
||
call crlf ; throw a newline or two
|
||
ld a,(#dtroff)
|
||
cp 0xc9
|
||
call nz,dtron ; enable dtr
|
||
ld c,getdrv ; now, in case we changed drive / user in the
|
||
call bdos ; entry hook, we get the current drive / user
|
||
ld (curdrv),a
|
||
ld (chtdrv),a ; chat drive
|
||
ld c,gsuser
|
||
ld e,0xff
|
||
call bdos ; find out which user
|
||
ld (curusr),a ; save it away as well
|
||
ld (chtusr),a ; chat user
|
||
ld hl,0x80 ; get command tail
|
||
ld e,(hl) ; get it's length
|
||
ld (hl),' ' ; add a space so that byp will grok it
|
||
inc hl
|
||
ld d,h ; extend length to de
|
||
ex de,hl
|
||
add hl,de
|
||
ld (hl),d ; stick a zero byte on the end of it
|
||
ex de,hl ; base address back to hl
|
||
call byp ; was there anything there?
|
||
or a
|
||
call nz,ichat ; yes - go process it
|
||
|
||
; this loop provides terminal mode: it simply loops round polling the kdb &
|
||
; modem port - when it finds something, then it starts to get clever
|
||
|
||
.extern main
|
||
main: ld sp,(memtop) ; since we long jump here occasionally
|
||
ld hl,main
|
||
push hl ; push "here" so a return gets us back
|
||
ld a,lf_bit
|
||
ld (mode),a ; reset mode
|
||
call lstmod ; keep the printer going and check modem port
|
||
ld hl,(fkptr)
|
||
ld a,(hl)
|
||
or a ; sending a function key?
|
||
jr z,nofkey ; nope, go try the keyboard
|
||
call conin ; get the key
|
||
jr gotcon
|
||
nofkey: ld (prmpfl),a
|
||
ld a,(more)
|
||
rra ; should we get a keyboard character
|
||
jr c,skipin ; skip if not
|
||
call kbdsts ; keyboard ready?
|
||
or a
|
||
ret z ; no, loop back
|
||
call kbdin ; get the char
|
||
skipin: ld b,0 ; set b so a return is a no-op
|
||
call #kbmap ; run through the keyboard window
|
||
srl b
|
||
ret c ; swallowed, start again
|
||
gotcon: ld c,a ; save in c
|
||
ld a,b ; copy more bit to a
|
||
ld (more),a ; and save it
|
||
ld de,escstt
|
||
ld a,(de) ; what state are we in?
|
||
dec a
|
||
ld a,c ; get char back
|
||
jr z,hadesc ; we've had an esc char, handle next
|
||
ld hl,cschr
|
||
cp (hl)
|
||
call z,gotxof ; note passing xoff's
|
||
jr z,noxon
|
||
ld hl,lxoff
|
||
inc (hl)
|
||
dec (hl)
|
||
ld hl,escval
|
||
jr nz,noxon
|
||
cp (hl)
|
||
call nz,gotxon ; and xon's
|
||
noxon: cp (hl) ; test the char for an escape
|
||
jr nz,modopj ; no it's not, send it to the modem
|
||
ld hl,(fkptr)
|
||
ld a,(hl) ; in the midst of a pfk send?
|
||
or a
|
||
ld a,(escval) ; get an escape char back into a
|
||
modopj: jr z,gotesc ; yes - skip the usual escape
|
||
ld a,(wflg)
|
||
or a
|
||
ld a,c
|
||
call nz,limitb ; legal character?
|
||
ret c ; nope - exit now
|
||
modjp: jp modop
|
||
|
||
; gotesc - we just got the escape char in state 0: set state to 1
|
||
|
||
gotesc: ex de,hl
|
||
inc (hl) ; set state to 1
|
||
ret
|
||
|
||
; esctbl - table of special values for the escape handler
|
||
|
||
.dseg
|
||
esctbl: dw modop
|
||
.extern escval
|
||
escval: db escchr
|
||
table '?',help
|
||
table '.',break
|
||
table 0x2c,hangup
|
||
table 'B',baud
|
||
table 'C',catch
|
||
table 'D',dir
|
||
table 'E',echo
|
||
table 'H',hdxtog
|
||
table 'I',info
|
||
table 'J',jctog
|
||
table 'K',ldfnk
|
||
table 'L',lftog
|
||
table 'M',msbtog
|
||
table 'N',newdsk
|
||
table 'O',optog
|
||
table 'P',print
|
||
table 'Q',quit
|
||
table 'R',recv
|
||
table 'S',send
|
||
table 'T',type
|
||
table 'U',#user
|
||
table 'V',vttog
|
||
table 'W',witog
|
||
table 'X',chat
|
||
table 'Y',hold
|
||
table 'Z',cclose
|
||
tblend:
|
||
.cseg
|
||
|
||
; hadesc - we are in state 1 and a char arrived: process it as appropriate
|
||
|
||
hadesc: ex de,hl
|
||
dec (hl) ; reset state
|
||
nowjp: ld a,c
|
||
ld hl,esctbl ; get address of table
|
||
ld b,{tblend - esctbl} / 3
|
||
call ucsa ; force it upper case
|
||
escscn: ld e,(hl)
|
||
inc hl
|
||
ld d,(hl) ; get jump address to de
|
||
inc hl
|
||
cp (hl) ; test for a match
|
||
inc hl
|
||
push de
|
||
ret z ; got it: go and process
|
||
pop de
|
||
djnz escscn ; loop back & try again
|
||
nowpop: ld a,c ; get char from c (again)
|
||
sub '0'
|
||
cp 10 ; check for '0' thru '9'
|
||
ret nc ; didn't find it - give up
|
||
add a,a
|
||
add a,a
|
||
add a,a
|
||
add a,a ; * 16 gives table offset
|
||
ld l,a
|
||
ld h,0
|
||
ld de,fktbl
|
||
add hl,de ; index into table
|
||
ld a,(hl) ; pick up
|
||
ld (fkdely),a ; and save delay flag
|
||
inc hl ; point at main string
|
||
ld (fkptr),hl ; save string address
|
||
ret
|
||
|
||
.dseg
|
||
escstt: db 0 ; state of escape detection
|
||
more: db 0 ; keyboard window code
|
||
|
||
; V4.1e rev
|
||
;
|
||
; we now save ix and iy through all patch and bios calls: these entries
|
||
; are used, and do all the work needed
|
||
|
||
.cseg
|
||
|
||
.macro access entry
|
||
.extern entry
|
||
entry:
|
||
push ix
|
||
push iy
|
||
call #`entry
|
||
pop iy
|
||
pop ix
|
||
ret
|
||
.endm
|
||
|
||
access kbdsts
|
||
access scrout
|
||
access modist
|
||
access modin
|
||
access modost
|
||
access modout
|
||
access sbreak
|
||
access ebreak
|
||
access dtroff
|
||
access dtron
|
||
access setbd
|
||
access setmod
|
||
access moveto
|
||
|
||
.extern kbdcc ; get a keyboard character if it's waiting
|
||
kbdcc:
|
||
call kbdsts
|
||
or a
|
||
ret z ; return 0 if nothing
|
||
|
||
access kbdin
|
||
|
||
.var #bdos 5
|
||
|
||
|
||
.extern usrbds ; call bdos, but with a user switch
|
||
usrbds:
|
||
push bc ; save the function code
|
||
ld a,(de) ; get the user number to switch to
|
||
inc de ; point de at bdos's idea of the fcb
|
||
push de ; save the address
|
||
ld e,a
|
||
ld c,gsuser
|
||
call bdos ; set the user number
|
||
pop de ; restore the fcb address
|
||
pop bc ; and function number
|
||
|
||
.extern bdos
|
||
bdos:
|
||
push ix
|
||
push iy
|
||
call #bdos
|
||
pop iy
|
||
pop ix
|
||
ret
|
||
|
||
.extern #subchk
|
||
#subchk:
|
||
ld hl,(1)
|
||
ld a,l
|
||
ld de,3
|
||
xor e
|
||
jr nz,chngit
|
||
ld l,a
|
||
ld b,6
|
||
jplp: ld a,(hl)
|
||
cp 0xc3
|
||
jr nz,chngit
|
||
add hl,de
|
||
djnz jplp
|
||
ret
|
||
chngit: ld hl,jptab
|
||
ld de,0x0103
|
||
ld bc,9
|
||
ldir
|
||
ret
|
||
|
||
jptab: jp locst
|
||
jp locin
|
||
jp locout
|
||
|
||
locst: ld hl,peekc
|
||
ld a,(hl)
|
||
.dseg
|
||
peekc: db 0
|
||
.cseg
|
||
or a
|
||
ret nz
|
||
ld c,6
|
||
ld e,-1
|
||
push hl
|
||
call 5
|
||
pop hl
|
||
ld (hl),a
|
||
or a
|
||
ret
|
||
|
||
locin: call locst
|
||
jr z,locin
|
||
ld (hl),0
|
||
ret
|
||
|
||
locout: res 7,c
|
||
ld e,c
|
||
ld c,6
|
||
jp 5
|
||
|