Term-Mite ST Smart Terminal/TermMite.asm

From Computer History Wiki
Jump to: navigation, search

This code was produced by Jon Elson, ca. 1985; it was used to make some tweaks to the video sync timing on his Term-Mite.

It was apparently produced by dumping the PROMs, and then dis-assembling the code; a set of listings of the original which came with the Term-Mite was likely used as a guide through the code in this process.

; steve Ciarcia term-mite standard program rom
; mod 1/3/85 to change sync pulse delays
;
;disassembled by Jon Elson's disns455 program
;Known bugs in the term-mite :
; 1	when in no-parity mode, parity is still checked on control chars
;	such as cr, lf, etc.
; 2	escape code handler table is unprotected -- unknown escape sequences
;	make random jumps in the program.
; 3	in show control-codes mode, esc sequences are still processed-
;	this is exactly what sho ctrl mode is used for-to verify that esc
;	seqs are being sent right
; 4	switch 1, pos 7 is : on=hi/lo intensity   off=F0 clock
; 5	switch 1, pos 4 & 5 are interchanged in manual
; 6	if CTS is not true, terminal locks up in tight loop and must be reset.
;	should give error msg on status line after timeout
; 7	not only is 8th bit ignored, also will not send NULL char
;
;
;  register usage
;
; r5  --  current line #
; r6  --  current col  #
; r7  --  general status
;	0	aux on
;	1	kbd on
;	2	3 char esc flag
;	3	4 char esc flag
;	4	fdx
;	5	on line
;	6	sho ctl mode
;	7	last char was escape
;
; r20 --  outqueue index -- for chars taken from input queue
; r21 --  inque index
; r22 .. 36  receive queue
; r37 --  stores char from esc/i
; r3e --  stores first data char (x pos) from esc/m sequence
;
; flags -	f0 - time to scan scanned keyboard
rstvec	jmp reset	;start of prog from system reset
	nop
	jmp extint	;loc 3 - external interrupt vector
	nop
	nop
	jmp	intint	;loc 9 - internal interrupt vector
reset	call getsw1
	jb0 stok	;if sw1.1 off, skip self test
	jb5 inttest	;if sw1.6 on , "internal test"
	sel mb1		;jump to external memory
	jmp rstvec	;wait for switch to be thrown
inttest	dis ii		;disable all interrupts
	dis xi
	mov r0,#3FH	;test internal ram memory
stlup	mov a,#0AAH	;test regs with pattern=AA
	mov @r0,a
	mov a,@r0
	cpl a		;1's compl pattern
	mov @r0,a
	mov a,@r0
	xrl a,#55H	;check result
	jnz L0025	;error
	djnz r0,stlup	;loop until all regs tested
	call bell	;beep once
L0025	mov a,#01H	;both recv & xmit at same baud rate
	mov umx,a
	mov a,#41H	;loop back, 8 bit chars
	mov ucr,a
	mov r0,#3DH
	mov a,#02H
	mov @r0,a
	mov r4,a
sthispd	mov r2,a	;test uart with AA & 55
	call setbrm
stxwt	mov a,stat	;wait until xmtr ready
	cpl a
	jb5 stxwt
	mov a,#0AAH
L003A	out xmtr
	mov r1,#60H
stdly	call dlaysub	;delay 60H x dlaysub
	djnz r1,stdly
	mov a,stat	;recv buf better be full
	cpl a
	jb0 sterror	;error - recv buffer not full
	in rcvr		;get char recv'd
	cpl a		;change AA to 55 and do again
	djnz r2,l003a
	xrl a,#55H	;check result
	jnz sterror
	mov a,#02H	;do again with a different baud rate
	mov @r0,#0DH
	djnz r4,sthispd
	call bell	;beep again if all ok
	jmp stok
sterror	in rcvr		;clear garbage perhaps left in receiver
stok	mov r0,#3FH	;clear all regs
	clr a
iniclrr	mov @r0,a
	djnz r0,iniclrr
	call L02CF
	mov ucr,a
	call getsw1	;get switch #1
	mov r2,a	;save
	mov r4,#25H
	jb2 dkbkgnd	;if dark-bkgnd then r4=25 else r4=2d
	mov r4,#2DH
dkbkgnd	jb1 L0070
	xch a,r4
	orl a,#10H
	xch a,r4
L0070	mov a,#0DH	;set cursor size
	mov tcp,a
	mov a,r2	;get sw1 again
	jb4 L007A	;if block cursor then csr=0F else csr=79
	mov a,#79H	;1 line cursor
	jmp L007C
L007A	mov a,#0FH	;full block cursor
L007C	mov @tcp,a
	mov a,r2	;get sw1 again
	jb3 L0084	;if not blink cursor then r4=r4 OR 2
	mov a,r4
	orl a,#02H
	mov r4,a
L0084	mov a,r2	;get sw1 again, check dual intens/F0 clock
	cpl a
	anl a,#40H
	orl a,#14H	;scr=bus mode, 9 dots/cell, sequential, clk / 1
	mov scr,a	;set system control reg
	call getsw3	;get switch # 3
	swap a		;move baud rate bits to lo nibble
	anl a,#0FH	;mask baud rate bits
	mov r3,a
	mov r0,#3DH
	mov @r0,a	;store baud rate at r3d
	call setbr	;set the baud rate
	jmp ldvtmg	;load video timing chain (continue with init sequence)
;
;
setbrm	mov r0,#3DH	;set baud rate from memory (reg 3d)
	mov a,@r0
	mov r3,a
setbr	add a,#0B6H	;set baud rate without affecting memory (reg 3d)
	movp a,@a
	mov psr,a	;set prescale reg (hi 4 bits=prescale, lo 3 bits=hi baud rate divisor)
	mov a,r3
	add a,#0A6H
	movp a,@a
	mov baud,a	;set baud rate reg (low 8 bits of baud rate divisor)
	ret
;  this is the baud rate divisor table
lbdtbl	db	018H,059H,0ffH,07fh,0bfh,05fh,03fh,02fh
	db	01fh,017h,00fh,00bh,005h,005h,005h,017h
hbdtbl	db	064h,063h,062h,061h,060h,060h,060h,060h
	db	060h,060h,060h,060h,060h,060h,060h,060h
;
ldvtmg	clr a		;load video timing chain
	mov tcp,a	;point tcp at tcp reg 0
	mov a,r2	;get sw1 from a while back
	sel rb1
	jb7 hz60	;jmp if 60 Hz
	mov r2,#7EH	;50 hz H len
	mov r5,#0B9H	;50 hz char scan height
	mov r3,#0CCH	;50 hz blink rate
	jmp ldvtog
hz60	mov r2,#67H	;60 hz H len
	mov r5,#98H	;60 hz char scan height,9 extra scans at end of frame
	mov r3,#0ACH	;60hz blink rate, 50% duty cycle
ldvtog	mov a,r2
	mov @tcp,a	;set H len
	mov a,#4FH
	mov @tcp,a	;set HBR - Horiz blank begin
	mov a,#56H
	mov @tcp,a	;set HSBR- Horiz sync begin
	mov a,#65H
	mov @tcp,a	;set HSER - Horiz sync end
	mov a,r5
	mov @tcp,a	;set CSHR - Char scan height in Hi nibble, ES/F in LO
	mov a,#1AH
	mov @tcp,a	;Vertical length
	mov a,#18H
	mov @tcp,a	;Vertical blanking
	mov a,#08H
	mov @tcp,a	;Vertical sync begin
	mov a,#17H
	mov @tcp,a	;Status row begin
	mov a,r3
	mov @tcp,a	;Blink rate
	mov a,#30H
	mov @tcp,a	;gfx col reg
	mov a,#35H
	mov @tcp,a	;gfx row
	mov a,#89H
	mov @tcp,a	;underline size = 8 (hi) 9 (lo)
	sel rb0
	mov a,r4
	mov vcr,a
	call L052B
	mov endd,a
	mov srow,a
	clr a
	mov hacc,a
	mov begd,a	;beginning of display ram = 0000
	mov home,a	;home address = 0000	(this changes with scrolling)
	mov vint,a	;vertical interrupt reg <= 0
	mov a,#0FFH
	mov al0,a	;attribute latch <=ff (none)
	mov r0,#37H	;r37 <= ff
	mov @r0,a
	mov a,#0FCH	;attribute latch1<=FC (reverse, half intens)
	mov al1,a
	call getsw2	;read sw # 2
	mov r4,a
	anl a,#30H	;mask off all but HDX/FDX & local/on-line (bits 5,6)
	orl a,#02H
	mov r7,a	;set r7 with fdx,on-line switches, and enable kbd
	mov a,r4	;get sw2 back
	rr a		;move split baud switches to a1,0
	anl a,#07H	;keep xmit/rcv slow & split baud divisor
	add a,#lo spbdtb ;index into split baud rate table
	movp a,@a
	mov umx,a	;load uart multiplex reg
	mov a,r4	;get sw2 back
	jb6 L012A	;jmp if encoded kbd
	mov a,#0FFH	;load timer with -1 and start (a short time)
	mov t,a
	strt t
L012A	mov a,#50H	;enab timer int & uart rcv buf full masks
	mov mask,a
	orl port,#40H	;drop rts
	mov r1,#3FH
	mov @r1,#07H	;to fill mem?
L0133	mov a,#10H	;move 1000 to cursor address
L0135	mov hacc,a
L0136	mov r0,a	;ro <= 10h
	clr a
L0138	mov curs,a	;set curs addr
	mov a,@r1	;r1->r3f = 07h
	movx @curs,a	;write 07h into video mem (attributes =?)
	mov a,curs
	inc a
	jnz L0138	;continue until lo a =0
	djnz r0,L0138	;do above 10H times
	mov hacc,a
	mov curs,a
	call updstat
	en xi
	en ii
	jmp clrscrn
spbdtb	db	020h,010h,040h,010h,0a0h,090h,084h,081h
	page
;	internal interrupt handler
intint	sel rb1
	mov r7,a
	mov a,intr	;find out which device
nxtint	mov r5,a
	jb4 rcvchar	;uart recv full
	jb6 timer	;timer interrupt
	xch a,r7
	sel rb0		;all ints have been serviced, return
	retr
timer	mov r0,#3CH
	mov a,@r0
	jb6 L0162
	cpl f0		;set semaphore for keyboard scanner
L0162	mov a,r5	;cut real time and timer interrupts from INTR reg copy
	anl a,#3FH
	jmp	nxtint	;check for other ints
rcvchar	mov r1,#07H
	mov a,@r1
	cpl a
	mov r1,#1AH	;if on-line - put char in r1a, if local put in screen queue
	jb5 L0171	;jmp if on line
	call gqueptr	;get address of where to put char in queue
L0171	in rcvr		;get char from uart
	mov @r1,a	;enqueue
	anl a,#0FEH	;if char was 0 or 1, don't check status ???
	jz L017E
	mov a,stat	;check for overrun, framing, parity error
	anl a,#0EH
	jz L017E	;no error
	mov @r1,#7FH	;error, replace char with blot
L017E	mov a,r5	;cut RT,recv,xmtr emty & xmtr buf emty from intr copy
	anl a,#63H
	jmp	nxtint	;check for other ints
	page
; scanned keyboard service routine
scankbd	clr f0
	mov a,r5
	mov hacc,a
	movl r0,a
	mov a,r7
	cpl a
	jb1 L01AC
	mov r0,#38H
	clr a
	mov @r0,a
	mov r2,#10H
L0191	mov a,r2
	dec a
	orl a,#40H
	out port
	call getsckb
	jnz L01DD
L019A	djnz r2,L0191
L019C	mov r0,#38H
	mov a,@r0
	jz L01A5
	add a,#0FCH
	jnc L01B1
L01A5	clr a
	mov r2,#05H
L01A8	mov @r0,a
	inc r0
	djnz r2,L01A8
L01AC	movl a,r0
	mov a,hacc
	mov r5,a
	jmp mainlp
L01B1	mov r2,#03H
L01B3	inc r0
	mov a,@r0
	jb7 L01C3
	jz L01C3
	call L01D5
	call L0205
	jb3 L01C7
	mov a,@r0
	orl a,#80H
	mov @r0,a
L01C3	djnz r2,L01B3
	jmp	L01AC
L01C7	mov r0,#3CH
	mov r3,#28H
	mov @r0,#40H
L01CD	call dlaysub
	djnz r3,L01CD
	mov @r0,#80H
	jmp	L01AC
L01D5	dis ii
	sel rb1
	cpl f0
	call L0335
	sel rb0
	en ii
	ret
L01DD	mov r3,a
	call dlaysub
	call getsckb
	xrl a,r3
	jnz L019A
	mov r0,#06H
	mov r4,a
	mov a,r3
	cpl a
	jb0 L01ED
	cpl f1
L01ED	jb0 L01F1
	call L0209
L01F1	rr a
	xch a,r4
	add a,#10H
	xch a,r4
	djnz r0,L01ED
	jmp	L019A
	page
dlaysub	mov a,#0FFH
L01FC	dec a
	jnz L01FC
	mov a,#0C8H
L0201	dec a
	jnz L0201
	ret
L0205	call getsckb
	mov a,hacc
	ret
L0209	mov r3,a
	mov a,r4
	add a,r2
	add a,#77H
	movp a,@a
L020F	xch a,r5
	mov a,r2
	add a,#0F2H
	jc L021F
	jf1 L021F
	call L0205
	jb1 L0223
	jb0 L0231
	jb2 L0228
L021F	clr f1
	mov a,r5
	jmp L0253
L0223	mov a,r5
	anl a,#1FH
	jmp L0253
L0228	mov a,r5
	add a,#9FH
	jnc L021F
	add a,#0E6H
	jc L021F
L0231	mov a,#5CH
L0233	xrl a,r5
	jnz L023A
	mov r5,#40H
	jmp L021F
L023A	mov a,#0D4H
	add a,r5
	jnc L021F
	add a,#0FCH
	jc L0247
L0243	mov a,#10H
L0245	jmp L0252
L0247	mov a,#0C4H
	add a,r5
	jc L0250
L024C	mov a,#0F0H
	jmp L0252
L0250	mov a,#0E0H
L0252	add a,r5
L0253	jnz L0259
	call L01D5
	jmp	L019C
L0259	dis ii
	mov r5,a
	xch a,r6
	mov hacc,a
	mov r6,#03H
	mov r1,#38H
	inc @r1
L0262	inc r1
	mov a,@r1
	jz L0271
	xrl a,r5
	anl a,#0DFH
	clr c
	rlc a
	jz L026F
	djnz r6,L0262
L026F	jmp L0273
L0271	mov a,r5
	mov @r1,a
L0273	mov a,hacc
	mov r6,a
	en ii
	xch a,r3
	ret
	page
;  keyboard encoder table
enctbl	db	01bh		;esc
	db	13h		;ctrl/s
	db	0ch		;ctrl/l (FF)
	db	0ah		;line feed
	db	0bh		;vert tab
	db	00h
	db	09h		;tab
	db	0eh		;ctrl/n
	db	08h		;back-space
	db	10h		;ctrl/p
	db	11h		;ctrl/q
	db	12h		;ctrl/r
	db	0fh		;ctrl/o
	db	'78923465718'	;digits row
	db	'\9-0'
	db	07eh		;tilde
	db	0,0,0
	db	'werytuqi'
	db	05fh		;underbar
	db	'o[p]'
	db	'456'		;numeric pad
	db	'sdfhgjak'
	db	0dh		;carriage ret
	db	'l:'
	db	03bh		;semi-colon
	db	'\'
	db	'123'		;numeric pad
	db	'xcvnbmz,'
	db	07fh		;rubout
	db	0,'/.',0
	db	'0',0,'.'	;numeric pad
	db	0,0,0,0,0,0
	db	' '		;space bar
	page
L02CF	call getsw3
	cpl a
	anl a,#0FH
	mov r3,a
	call getsw2
	rrc a
	mov a,r3
	rlc a
	mov r3,a
	ret
	page
;  get loc to put char into queue
gqueptr	mov r1,#21H	;r21 is ring buffer enqueue index
	mov a,@r1
	mov r2,a
	mov r3,a
	inc a
	xrl a,#15H	;check if time to wrap ring queue around
	jnz L02E8
	mov r3,#0FFH
L02E8	mov a,r3
	inc a
	mov @r1,a
	mov a,r2
	add a,#22H	;queue starts at r22, 14 hex long
	mov r1,a	;r1 is pointer to entry
	ret
lfandcr	call getsw2	;check lf+cr switch (for local mode)
	jb7 L02F8
	call gqueptr
	mov @r1,#0AH	;if on, shove in an extra lf
L02F8	ret
lfcr	call getsw2	;same as above for on-line mode
	jb7 L02F8
	mov r4,#0AH
	call SEND1CH
	mov r4,#0DH
	ret
; read setup dip switches into A
getsw1	mov a,#80H
	jmp getasw
getsw2	mov a,#0A0H
	jmp getasw
getsw3	mov a,#0C0H
	jmp getasw
getsckb	mov a,#0E0H
getasw	mov hacc,a
	movl r1,a
	movx a,@r1
	ret
SEND1CH	mov a,stat	;send 1 char out uart
	cpl a		;wait for xmit buf empty
	jb5 SEND1CH
s1cwait	in port		;check clear to send
	cpl a
	jb7 s1cgo
	anl port,#3FH	;raise request to send
	jmp s1cwait	;wait for clr to send
s1cgo	anl port,#7FH	
	mov a,r4	;get saved char
	out xmtr	;transmit char
	ret
L0327	sel rb1
	mov r4,a
	call SEND1CH
	sel rb0
	ret
	page
;	external interrupt handler
;		the only external int is the encoded keyboard
extint	sel rb1
	xch a,r7
	mov a,hacc
	xch a,r6
	in port		;read kbd char
	anl a,#7FH	;strip bit 7
	clr f0
L0335	mov r4,a	;put char in r4 (also entry from scanned kbd code)
	mov r0,#07H	;sel r7
	jnz L0340	;if char<>0 then r7=r7 AND df
	mov a,@r0	;get r7
	anl a,#0DFH	;set on-line/local bit to local ???
	mov @r0,a
	jmp L0353
L0340	mov a,@r0
	cpl a
	jb1 L035D
	mov a,@r0
	cpl a
	jb5 L0353
	call SEND1CH
	xrl a,#0DH	;is it cr ?
	jnz L0350	;no
	call lfcr	;send lf if lf+cr mode selected
L0350	mov a,@r0
	jb4 L035D	;test hdx/fdx bit, jmp if fdx
L0353	call gqueptr
	mov a,r4	;get kbd char in a
	mov @r1,a	;store in queue
	xrl a,#0DH
	jnz L035D
	call lfandcr
L035D	jnf0 realint	;if handler entered by kbd scanner rather than a real
	clr f0		;interrupt, we must return the right way. also clear
	ret		;kbd scan needed flag (f0)
realint	xch a,r6
	mov hacc,a
L0363	xch a,r7
	sel rb0
L0365	jnxi L0365	;spin waiting for ext int to go away
	retr		;return and restore psw
L0368	jmp escpcod
L036A	jmp scankbd
	page
;	main terminal service loop
mainlp	jf0 L036A	;if flag 0 set, scan kbd
	mov r0,#20H
	mov a,@r0	;r2 <= r20
	inc r0
	mov r2,a
	mov a,@r0	;a<=r21
	xrl a,r2
L0375	jz mainlp	;if outque index=inque index, no data in queue
	inc r0
	mov a,r0	;a<=22
	add a,r2	;add index
	mov r1,a	;save outque ptr
	dis xi
	dis ii
	mov a,@r1	;get char from queue
	mov r3,a	;save in r3
	dec r0
	dec r0		;point back at r20
	mov a,r2
	xrl a,#14H	;check if queue has wrapped around
	jnz L0388
	mov r2,#0FFH	;reset to beginning of ring buf queue
L0388	mov a,r2
	inc a		;bump index
	mov @r0,a	;write index to r20
	en ii
	en xi
	mov a,r7	;check if last char was esc
	jb7 L0368
	mov a,r3	;get char back
	anl a,#60H	;get which ascii 'stick'
	jnz L0397
	jmp cntlcod	;if a ctrl char
L0397	mov r0,#3FH
	mov a,curs
	mov r1,a
	mov a,hacc
	add a,#10H
	mov hacc,a
	mov a,r1
	movl r1,a
	mov a,@r0
	movx @r1,a
	mov r0,#37H
	mov a,@r0
	mov hacc,a
L03A7	mov a,r3
	movx @curs,a
	call L04E6
	mov a,r7
	cpl a
	jb0 L03B8
	mov a,#0F0H
	mov hacc,a
	movl r1,a
L03B3	movx a,@r1
	jb0 L03B3
	mov a,r3
	movx @r1,a
L03B8	inc r6
	mov a,r6
	add a,#0AFH
	jnc mainlp
	inc r5
	mov r6,#01H
	call L03F1
	jc L03CA
	mov a,curs
	call L03DB
	jmp L03D8
L03CA	dec r5
	call clrline
	mov a,home
	add a,#50H
	mov home,a
	call L03EA
	jnc L03D8
	clr a
	mov hacc,a
	mov home,a
L03D8	jmp mainlp
	page
clrline	mov a,home	; clear a line
L03DB	movl r0,a
	mov r2,#50H	;80 base 10
L03DE	dis ii
	mov a,#0FFH	;no attributes
	mov hacc,a
	mov a,#20H	;space
L03E4	movx @r0,a	;write space to video mem
	incl r0
	djnz r2,L03E4
	en ii
	ret
L03EA	mov a,home
L03EB	add a,#80H
	mov a,hacc
	add a,#0F8H
	ret
L03F1	mov a,r5
	add a,#0E7H
	ret
L03F5	clr c		;sets cy if curs=00xx
	mov a,hacc
	xrl a,#0FFH
	jnz L03FC
	cpl c
L03FC	ret
	page
; process control chars
; an error here is that 'show control codes' mode should be tested first
cntlcod	mov a,r3	;get char
	xrl a,#1BH	;see if esc
	jz ctlesc
	mov a,r7
	jb6 shoctrl	;in show ctrl chars mode
	mov a,r3	;get char
	jnz L0412
	jmp illesc	;illegal esc seq, sho stat line and return to main loop
shoctrl	mov a,r3	;show control codes
	orl a,#0C0H	;force ctrl code to upper case, rev. video
	mov r3,a
	call L078B
	jmp L03A7
L0412	add a,#0EBH	;greater than 14H ?
	jc L043C
	mov a,r3	;get char
	add a,#0F9H
	jnc L0457	;ignore
	add a,#1EH	;add table index
	jmpp @a
ctltbl	db	lo cbell ;control chars jump table - starts with ctrl/g
	db	062h
	db	086h
	db	0abh
	db	0c5h
	db	02ch
	db	0dfh
	db	030h
	db	032h
	db	062h
	db	034h
	db	036h
	db	038h
	db	03ah
	mov	r1,#3fh	;off page jumps for ctrl char table
	jmp L0133
	jmp L050A
	jmp L0520
	jmp L0531
	jmp L0542
	jmp L054A
	jmp L0559
L043C	add a,#42H
	movp a,@a
	mov r3,a
	jmp L0397
	inc r2
	mov srow,a
	inc r4
	orl a,r2
	anl a,r0
	orl a,r4
	anl a,r6
	anl a,r2
	orl a,r6
	inc r6
	anl a,r4
	page
;  ctrl char was escape
ctlesc	xch a,r7	;set r7.7, clr r7.3
	orl a,#80H
	anl a,#0F7H
	xch a,r7
	mov r0,#3EH
	mov @r0,#00H
L0457	jmp mainlp
cbell	call bell	;beep and back to mainloop
	jmp mainlp
bell	anl port,#0DFH	;trigger the one shot on the port
	orl port,#20H
	ret
L0462	mov a,r6
	xrl a,#01H
	jz L0469
	djnz r6,L047A
L0469	mov r6,#50H
	dec r5
	mov a,r5
	jnz L0471
	mov r5,#18H
L0471	mov a,curs
	dec a
	call L03F5
	jnc L047A
	call L052B
	mov curs,a
L047A	dec curs
	mov a,r3
	xrl a,#08H
	jnz L0484
	movx a,@curs
L0481	mov a,#20H
	movx @curs,a
L0484	jmp mainlp
	mov a,r6
	mov r4,a
	add a,#08H
	anl a,#0F8H
	inc a
	mov r6,a
	add a,#0AFH
	jnc L049C
L0492	dec curs
	djnz r4,L0492
	inc curs
	mov r6,#01H
	call L04AF
	jmp L04A9
L049C	mov a,curs
	add a,#08H
	anl a,#0F8H
	mov curs,a
	call L03EB
	jnc L04A9
	clr f1
	call L04FE
L04A9	jmp mainlp
	page
;  preform line feed
lfhand	call L04AF
	jmp mainlp
L04AF	inc r5		;bump line counter to next line
	call L03F1	;check if on bottom line
	jnc L04C2	;no - don't scroll
	dec r5		;yes, put line # back to 18 and scroll instead
	call clrline	;clear a line
	mov a,home	;move the home line down one
	add a,#50H	;...by adding 80 to it
	mov home,a
	call L03EA
	jnc L04C2	;if no carry, ok
	clr a		;otherwise, we have wrapped all the way around,
	mov hacc,a	;so put home back to first place in memory
	mov home,a
L04C2	call L04EB
	ret
	mov r4,#08H
L04C7	call L04AF
	djnz r4,L04C7
	jmp mainlp
clrscrn	mov r5,#18H	;clear entire screen (24 lines)
	clr a
	mov hacc,a
	mov home,a
	mov curs,a
L04D3	call clrline
	mov a,home
	add a,#50H
	mov home,a
	djnz r5,L04D3
	mov a,curs
	mov home,a
	jmp L0544
crhand	dec curs	;carriage return handling
	djnz r6,crhand	;back up cursor column_no times
	inc curs
	inc r6
	jmp mainlp
L04E6	clr f1
	inc curs
	mov a,curs
	jmp L04EF
L04EB	cpl f1
	mov a,curs
	add a,#50H
L04EF	movl r0,a
	mov a,r6
	xrl a,#48H
	jnz L04F7
	call bell
L04F7	movl a,r0
	call L03EB
	jc L04FE
	jmp L0506
L04FE	clr a
	mov hacc,a
	movl r0,a
	jnf1 L0506
	mov a,r6
	dec a
	mov r0,a
L0506	clr f1
	movl a,r0
	mov curs,a
	ret
L050A	mov r1,#50H	;back up cursor 1 full line
L050C	dec curs
	djnz r1,L050C
	mov a,curs
	call L03F5
	jnc L051A
	call L052B
	mov a,#2FH
	add a,r6
	mov curs,a
L051A	djnz r5,L051E
	mov r5,#18H
L051E	jmp mainlp
L0520	inc r5
	call L03F1
	jnc L0527
	mov r5,#01H
L0527	call L04EB
	jmp mainlp
L052B	mov a,#07H
	mov hacc,a
	mov a,#80H
	ret
L0531	call L04E6
	inc r6
	mov a,r6
	add a,#0AFH
	jnc L0540
	mov r6,#01H
	inc r5
	call L03F1
	jc L0542
L0540	jmp mainlp
L0542	mov a,home
	mov curs,a
L0544	mov a,#01H
	mov r5,a
	mov r6,a
	jmp mainlp
L054A	call L02CF
	orl a,#20H
	mov ucr,a
	mov r2,#96H
L0551	call dlaysub
	djnz r2,L0551
	mov a,r3
	mov ucr,a
	jmp mainlp
L0559	mov r0,#3DH
	inc @r0
	mov a,@r0
	anl a,#0FH
	mov @r0,a
	call setbrm
	jmp L05FF
	page
;  escape code handling
escpcod	anl a,#7FH	;turn off esc flag in r7
	jb2 esc3ch
	jb3 L05A3
	xch a,r7	;put r7 back
	mov a,r3	;get char
	add a,#0BFH	;offset for 'A'
	jb7 illesc	;if less than 'A', do nothing
	add a,#73H	;index to table
	jmpp @a
esctbl	db	0e7h	;A
	db	0ffh	;B
	db	0efh	;C
	db	0a5h	;D
	db	0a9h	;E
	db	0f3h	;F
	db	0aeh	;G
	db	0c0h	;H
	db	0c5h	;I
	db	09fh	;J
	db	0f7h	;K
	db	003h	;L
	db	08ch	;M
	db	09fh	;N
	db	0fbh	;O
	db	08eh	;P
	db	090h	;Q
	db	092h	;R
	db	094h	;S
	db	096h	;T
	db	09fh	;U
	db	0d9h	;V
	db	09fh	;W
	db	0ebh	;X
	db	098h	;Y
	jmp esc$m	;OFF PAGE JMPS - esc/M
	jmp L060F
	jmp inttest	;esc/Q - reset and self test
	jmp L0638
L0594	jmp L064A
	jmp L0670
L0598	jmp L067E
setb7	orl a,r7
	jmp L059E
clrb7	anl a,r7
L059E	mov r7,a
illesc	call updstat	;on illegal esc seq - update status line and return to loop
	jmp mainlp
L05A3	jmp L06A5
L05A5	mov a,#20H
	jmp L05AB
	mov a,#10H
L05AB	xrl a,r7
	jmp L059E
	mov r3,#7FH
L05B0	call L0733	;strip bit 7 from status line (rev vid?)
	movl r0,a
	mov r1,#50H
L05B5	movx a,@r0
	anl a,#7FH
	movx @r0,a
	incl r0
	djnz r1,L05B5
	mov a,r3
	mov al1,a
	jmp mainlp
	mov a,#0FCH
	mov al1,a
	jmp illesc
	mov a,r7
	orl a,#84H	;turn on esc & r7.2 flags for 3 char esc seq
	jmp L059E
esc3ch	jb3 L05DE	;if r7.2 on bit 3 off, then 3 char esc seq is complete
	anl a,#7BH	;remove bit 2
	mov r7,a
	mov r0,#37H	;store char in r37
	mov a,r3
	mov @r0,a
	call getsw1	;check if internal attributes
	jb1 L05B0
	jmp mainlp	;ignore
	mov a,r7
	orl a,#8CH
	jmp L059E
L05DE	anl a,#73H	;turn off all esc func bits
	mov r7,a
	mov r0,#3FH	;put char in 3f
	mov a,r3
	mov @r0,a
	jmp mainlp
	mov a,#01H	;aux printer on
	jmp setb7
	mov a,#0FEH	;aux printer off
	jmp clrb7
	mov a,#40H	;ctl mode on
	jmp setb7
	mov a,#0BFH	;ctl mode off
	jmp clrb7
	mov a,#02H	;
	jmp setb7
	mov a,#0FDH
	jmp clrb7
L05FF	call L0739
	jmp mainlp
	mov a,hpen
	add a,#20H
	call L0327
	mov a,vpen
	add a,#20H
	call L0327
	jmp mainlp
L060F	dis ii
	orl port,#80H
	mov a,home
	movl r0,a
	mov r2,#18H
	mov a,#0F0H
	mov hacc,a
	movl r1,a
L061A	mov r3,#50H
L061C	movx a,@r1
	jb0 L061C
	movx a,@r0
	movx @r1,a
	incl r0
	djnz r3,L061C
L0624	movx a,@r1
	jb0 L0624
	mov a,#0DH
	movx @r1,a
	movl a,r0
	call L03EB
	jnc L0632
	clr a
	mov hacc,a
	movl r0,a
L0632	djnz r2,L061A
	anl port,#7FH
	jmp L0666
L0638	mov a,r6
	dec a
	mov r3,a
	jz L0666
	mov a,curs
L063E	dec a
	djnz r3,L063E
	movl r0,a
	mov a,r6
	dec a
	mov r3,a
	dis ii
	call L0669
	jmp L0666
L064A	mov a,home
	movl r0,a
	mov a,r5
	mov r2,a
	dis ii
L064F	mov a,r2
	xrl a,#01H
	jz L0638
	mov r3,#50H
	call L0669
	mov a,#0DH
	call L0327
	movl a,r0
	call L03EB
	jnc L0664
	clr a
	mov hacc,a
	movl r0,a
L0664	djnz r2,L064F
L0666	en ii
	jmp mainlp
L0669	movx a,@r0
	call L0327
	incl r0
	djnz r3,L0669
	ret
L0670	clr f1
L0671	mov a,curs
	movl r0,a
	mov a,r6
	cpl a
	add a,#52H
	mov r2,a
	call L03DE
	jnf1 L0699
	clr f1
	ret
L067E	cpl f1
	call L0671
	inc r5
	call L03F1
	jc L0698
	mov a,r5
	cpl a
	add a,#1AH
	mov r4,a
L068B	movl a,r0
	call L03EB
	jnc L0693
	clr a
	mov hacc,a
	movl r0,a
L0693	movl a,r0
	call L03DB
	djnz r4,L068B
L0698	dec r5
L0699	jmp mainlp
esc$m	xch a,r7	;esc/M - 4 char esc seq
	orl a,#88H	;set flags to get rest of sequence
	xch a,r7
	clr a
	mov r1,#3EH	;clear r3e - indicates next char is 3rd of 4
	mov @r1,a
	jmp mainlp
L06A5	mov r1,#3EH	;handles 3rd & 4th chars of 4 char esc
	clr a		;checking if 3rd or 4th
	xrl a,@r1
	jnz L06C0	;if a char is in r3e (x coord) we now have 4th char
	mov a,r3	; no - get 3rd char (x coord)
	add a,#0E0H
	jc L06B1
	clr a
L06B1	mov r3,a
	add a,#0AFH
	jnc L06BA
	mov a,#50H
	jmp L06BB
L06BA	mov a,r3	;get char
L06BB	inc a
	mov @r1,a	;put x addr in r3e, so we have it next time thru...
	mov r6,a	;and it also indicates that we have already got 3rd
	jmp mainlp
L06C0	mov a,r3	;now process the 4th
	add a,#0E0H	;char offset
	jc L06C6
	clr a
L06C6	mov r3,a
	add a,#0E6H
	jnc L06CF
	mov a,#18H
	jmp L06D0
L06CF	mov a,r3
L06D0	mov r4,a
	inc a
	mov r5,a
	mov a,home
	mov curs,a
L06D5	mov a,r4
	jz L06DC
	call L04EB
	djnz r4,L06D5
L06DC	mov a,curs	;move cursor
	add a,@r1
	dec a
	mov curs,a
	xch a,r7
	anl a,#77H	;turn off esc and r7.3 flags
	xch a,r7
	jmp mainlp	;done
	page
;  status line handling
L06E6	call L0733
	movl r1,a
	mov r2,#50H
	call L078B
	mov a,#0A0H
L06EF	movx @r1,a	;mover : r1 = lo cursor addr of start of string
	incl r1		;r2 = addr of string
	djnz r2,L06EF	;r3 = char count
	ret
L06F4	mov r1,#0CAH	;move 'ready'
	mov r2,#0D0H
	jmp L071A
L06FA	mov r1,#80H	;on line
	mov r2,#0D5H
	jmp L0722
L0700	mov r1,#90H	;key off
	mov r2,#0E0H
	mov r3,#07H
	jmp L072C
L0708	mov r1,#8AH	;fdx
	mov r2,#0EDH
	jmp L0712
L070E	mov r1,#8AH	;hdx
	mov r2,#0F0H
L0712	mov r3,#03H
	jmp L072C
L0716	mov r1,#80H	;local
	mov r2,#0DBH
L071A	mov r3,#05H
	jmp L072C
L071E	mov r1,#9CH	;aux on
	mov r2,#0E7H
L0722	mov r3,#06H
	jmp L072C
L0726	mov r1,#0A4H	;ctl mode
	mov r2,#0F7H
	mov r3,#08H
L072C	call L0733
	mov a,r1
	movl r1,a
	call wrstat
	ret
L0733	mov a,#07H
	mov hacc,a
	mov a,#80H
	ret
L0739	call L0733
	mov a,#0BEH
	movl r0,a
	call getsw3
	cpl a
	mov r2,#0B1H
	jb3 L0747
L0745	mov r2,#0B0H
L0747	call L078F
	jb2 L074D
	mov r2,#0B0H
L074D	call L078F
	incl r0
	jb1 L0754
	mov r2,#0B0H
L0754	call L078F
	incl r0
	jb0 L075B
	mov r2,#0B0H
L075B	call L078F
	call getsw2
	incl r0
	jb0 L0764
	mov r2,#0B0H
L0764	call L078F
	call L0733
	mov a,#0B2H
	movl r1,a
	call L078B
	mov r0,#3DH
	mov a,@r0
	add a,#00H
	da a
	mov r0,a
	swap a
	call L0784
	mov a,r0
	call L0784
	incl r1
	mov r2,#0F3H
	mov r3,#04H
	call wrstat
	call L079D
	ret
L0784	anl a,#0FH
	add a,#0B0H
	movx @r1,a
	incl r1
	ret
L078B	mov a,#0FEH
	mov hacc,a
	ret
L078F	mov r3,#0FEH		;select reverse video, full intens
	xch a,r3
	mov hacc,a
	xch a,r3
	xch a,r2
	movx @r0,a
	incl r0
	xch a,r2
	mov r2,#0B1H
	ret
updstat	call L06E6	;using r7 flags, update status line
L079D	mov a,r7
	jb5 L07A4
	call L0716
	jmp L07A6
L07A4	call L06FA
L07A6	mov a,r7
	jb4 L07AD
	call L070E
	jmp L07AF
L07AD	call L0708
L07AF	mov a,r7
	jb1 L07B4
	call L0700
L07B4	mov a,r7
	jb0 L07B9
	jmp L07BB
L07B9	call L071E
L07BB	mov a,r7
	cpl a
	jb6 L07C1
	call L0726
L07C1	call L06F4
	ret
wrstat	call L078B	;write chars to status line
	mov a,r2
	movp a,@a
	orl a,#80H
	movx @r1,a
	incl r1
	inc r2
	djnz r3,wrstat
	ret
rdytxt	db	'V 1.1'
OLTXT	DB	'ONLINE'
LOCTXT	DB	'LOCAL'
KOFTXT	DB	'KEY OFF'
AUXTXT	DB	'AUX ON'
FDXTXT	DB	'FDX'
HDXTXT	DB	'HDX'
BAUTXT	DB	'BAUD'
CTLTXT	DB	'CTL MODE'
	DB	0FFH
	end