; QTERM Version 4.2 Patch Area.

; This is an example of the Xerox patch code. It is included because
; it uses a SIO for serial communications, and can be changed to work
; with any other SIO / DART system with very little work. All that is
; needed is to disable the baud rate code, modify the terminal depen-
; dancy stuff, and alter siod and sioc to match the port addresses of
; the SIO (data and control) as needed, and it should work.

; This should be assembled with ZSM (available on all fashionable BBS's)
; like this:
; A>ZSM QT-XEROX
; and installed with ZPATCH:
; A>ZPATCH QTERM QT-XEROX

;======================================================================

; This is a ZSM version of the more generic QTERMPAT.AZM generated by
; D. Presberg & D. Goodenough

; Code as adapted from QTERM.COM from QTERM33A.LBR posted by David Goodenough
;  to BOSKUG RCP/M circa 12/27/88, and QTERM Vers. 4.x patch listing 8-Feb-89.

; D. Presberg dissasembled this with Z8E, 21-Jan-89.  Code labels taken from
;  D. Goodenough "qterm.z" example circa 8-Feb-89.

; This edit is for Xerox 820-II and 16/8. These use an SIO chip, port A, with a
;separate baud rate generator:  status port at 04, data port at 06, baud rate
;port at 0.
;  19-Feb-90, T. Carney, BCS/BOSKUG.

; D. Goodenough added break, dtr and mode stuff  2-23-89

; D. Goodenough upgraded to V4.2 (larger patch area, and more functions)

.var	sioc	6		; sio control port
.var	siod	4		; sio data port

.var	rxrdy	1		; receiver ready
.var	txrdy	4		; transmitter ready

.var	baud	0		; baud rate port

.var	yes	0xff		; true value
.var	no	0		; false value


.org	0x0110
modist:	in	a,(sioc)	;get modem input status  (Xerox status port)
	and	rxrdy		; (result to Z:   no inp. character available
	ret			;   is 0 at bit-0 (low order) ===>   Z==1    )

.org	0x0120
modin:	in	a,(siod)	;read modem input character (Xerox data port)
	ret

.org	0x0130
modost:	in	a,(sioc)	;get modem output status  (Xerox status port)
	and	txrdy		; (result to Z:  bit-2 ... see above)
	ret

.org	0x0140
modout:	out	(siod),a	;write modem output char. (Xerox data port)
	ret

.org	0x0150
sbreak:	ld	a,(setf)	;start "break"
	or	a		;do we have valid data in r3,r4,r5
	ret	z		;no - don't do it
	ld	hl,r5
	set	4,(hl)		; set the bit
	jp	sioout		; and go do it
	
.org	0x0160
ebreak:	ld	a,(setf)	;end "break"
	or	a
	ret	z		; don't do it unless r3, r4, r5 are valid
	ld	hl,r5
	res	4,(hl)
	jp	sioout		; go clear the bit

.org	0x0170
dtroff:	ld	a,(setf)	;drop DTR
	or	a
	ret	z		; don't do it unless r3, r4, r5 are valid
	ld	hl,r5
	res	7,(hl)
	jp	sioout

.org	0x0180
dtron:	ld	a,(setf)	;raise DTR
	or	a
	ret	z		; don't do it unless r3, r4, r5 are valid
	ld	hl,r5
	set	7,(hl)
	jp	sioout

.org	0x0190
setbd:	out	(baud),a	;set baud rate (value in A) (Xerox baud
	ret			;rate port)

; The Baud Rate Table has entries from 38400 baud down to 300 baud.
;   There are 2 bytes per entry.  The second byte determines if the entry is
;   enabled or disabled (ffh=enabled; 00=disabled).  The first byte is passed
;   as the A value to the setbd subroutine.

; Xerox 820-II, 16/8 have advertised values for rates up to 19200.  Not all 
; available low speeds are used by QTERM, however.

.org	0x01a0

baudtb:
b38400:	db	0,no		;  38400 baud
b19200:	db	0xf,yes		;  19200
b9600:	db	0xe,yes		;   9600
b4800:	db	0xc,yes		;   4800
b2400:	db	0xa,yes		;   2400
b1200:	db	7,yes		;   1200
b600:	db	6,yes		;    600
b300:	db	5,yes		;    300 baud


.org	0x01b0
setmod:	ld	(setf),a	; flag we've done a set
	jp	domod		; have to do this elsewhere

; Communication Mode Table.  Single byte values for 12 combinations of
;    number-of-bits(7/8), parity(none/even/odd), number-of-stop-bits(1/2).

.org	0x1c0

modetb:
n17:	db	0b10000000	;0x80, 7n1
n18:	db	0b11000000	;0xc0, 8n1
n27:	db	0b10001000	;0x88, 7n2
n28:	db	0b11001000	;0xc8, 8n2
e17:	db	0b10000011	;0x83, 7e1
e18:	db	0b11000011	;0xc3, 8e1
e27:	db	0b10001011	;0x8b, 7e2
e28:	db	0b11001011	;0xcb, 8e2
o17:	db	0b10000001	;0x81, 7o1
o18:	db	0b11000001	;0xc8, 8o1
o27:	db	0b10001001	;0x89, 7o2
o28:	db	0b11001001	;0xc9, 8o2

.org	0x01cc
resrvd:	db	0	; reserved for future use

.org	0x01cd
xfersz:	db	8	;number of K to read/write during file xfers
			;Must be 1 / 2 / 4 / 8.  Best left as 8 unless
			;  disk is verrrrry slow.  Drop to smaller value
			;  if too many timeouts occur during "protocol"
			;  file transfers (xmodem or kermit).

.org	0x01ce
speed:	db	4	;cpu speed (Mhz; use 4 for Xerox)

.org	0x01cf
escape:	db	'\e' 		;escape character (1bh=^[  Escape)

.org	0x01d0
signon:			;signon message
	db	'\e(Xerox 16/8 1984\e)\0'	;Puts message in normal video.

.org	0x01f0
clrs:	db	'z' & 0x1f, 0	;clear screen string (Control-Z)

.var	scrout	0x0109	;(a routine to print to CON: the
			;   character in C)
.var	decout	0x010c	;(a routine to print to CON: a decimal value
			;   in HL.  Is available for VT100 and the like.)

.org	0x0200
moveto:	push	hl	;move cursor to position in HL (Row,Col)
	ld	c,'\e'	; lead-in with Esc (the ASCII one; not QTERM's)
	call	scrout
	ld	c,'='	; 2nd lead-in is '='
	call	scrout
	pop	hl
	push	hl
	ld	a,h	; row value (top row is 0.)
	call	poff	; add offset and send it to screen
	pop	hl
	ld	a,l	; col value (leftmost col is 0.)
poff:	add	a,' '	; (adds 20h)
	ld	c,a
	jp	scrout	; (scrout returns from 'moveto's call)

; Terminal Capability Bits.  The eight bits stand for each of the following
;   strings.   They count from 01h=bright to 80h=clear-to-end-of-screen.

.var	b_brit	0b00000001	; 0: bright (1.)	-- NOT mandatory
.var	b_dim	0b00000010	; 1: dim    (2.)	-- NOT mandatory
.var	b_dlln	0b00000100	; 2: delete line (4.)	-- important
.var	b_inln	0b00001000	; 3: insert line (8.)	-- important
.var	b_dlch	0b00010000	; 4: delete character (16.)-- unused by QTERM
.var	b_inch	0b00100000	; 5: insert character (32.)-- NOT mandatory
.var	b_clel	0b01000000	; 6: clear to end-of-line(64.) -- important
.var	b_cles	0b10000000	; 7: clear to end-of-screen(128.)-- important

.org	0x022f
tcbits:	db	0xff		; capability bits: full support

.org	0x0230
brites:	db	'\e(\0'		;bright string (disable alternate video)

.org	0x0238
dims:	db	'\e)\0'		;dim string (enable alternate video)

.org	0x0240
dlstr:	db	'\eR\0'		;delete line (Esc-R)

.org	0x0248
ilstr:	db	'\eE\0'		;insert line (Esc-E)

.org	0x0250
dcstr:	db	'\eW\0'		;delete character (Esc-W))

.org	0x0258
icstr:	db	'\eQ\0'		;insert character (Esc-Q)

.org	0x0260
ceol:	db	'x' & 0x1f, 0	;clear to end of line (Control-X)

.org	0x0268
ceos:	db	'q' & 0x1f, 0	;clear to end-of-screen (Control-Q)

; Entry and Exit hooks.  These are provided to perform custom initialisation
; on startup and on exit from QTERM.  They are invoked before any use is made
; of the screen or the port hardware.

.org	0x0270
entry:	jp	do_ent		; entry hook (270h .. 272h)

.org	0x0273			; exit hook  (273h .. 275h)	
exit:	jp	do_exit		

.org	0x0276
user:	ret			; user subroutine (276h .. 278h)

.org	0x0279			; keyboard map routine  (279h .. 27bh)	
kbmap:	ret

.var	ilprmt	0x027c		; inline prompt routine lives at 27ch

; Extra patch area if needed.  280h .. 4ffh

.org	0x0280
patcha: 

do_ent:	ld	c,'z' & 0x1f	; Clear screen and home cursor.
	call 	scrout
	ld	c,'\e'		; Send 'Esc'...
	call	scrout		
	ld	c,'8'		; '8' to screen (set dim video mode)
	call	scrout		; (blink=4 or 6, graphics=5, inverse=7,
				; dim=8.
	ld	a,(b1200)	; entry hook (from 270h)
	call	setbd		;   Xerox setup for 1200 baud
	ld	a,(n18)		; and 8n1 communications mode.
	call	setmod
	ret

domod:	ld	c,a		; save byte in c
	ld	hl,r3		; look at byte for wr3
	res	7,(hl)		; turn off ms bit (Rx # bits / char)
	add	a,a		; move bit from 6 to 7 in a
	and	0x80		; mask off the rest
	or	(hl)		; or in the remainder
	ld	(hl),a		; and save it back
	inc	hl
	inc	hl		; point hl at r4
	ld	a,(hl)
	and	0xf4		; mask out bits we don't want
	ld	b,a		; save in b
	ld	a,c		; get set byte back
	and	0x0b		; get bits out of set byte that we want
	or	b		; or in the other bits
	ld	(hl),a		; and save it back
	inc	hl
	inc	hl		; point hl at r5
	ld	a,c
	and	0x40		; get the bit we want from c
	res	6,(hl)		; clear the bit in r5
	or	(hl)
	ld	(hl),a		; put new composite value back

sioout:	ld	hl,siodat
	ld	bc,6 * 256 + sioc
	otir
	ret

siodat:	db	3
r3:	db	0b11000001	; value for wr3 (0xc1)
	db	4
r4:	db	0b01000100	; value for wr4 (0x44)
	db	5
r5:	db	0b11101010	; value for wr5 (0xe5)

setf:	db	0		; flag if we've done a set mode command

do_exit:
	ld	c,'z' & 0x1f	; Clear screen and home cursor...
	call	scrout
	ld	c,'f' & 0x1f	; and restore original video mode
	call	scrout
	ret

; MUST end by 4ffh
