title 'Character I/O handler for MARC-BAB'

; Character I/O for the Modular CP/M 3 BIOS
; MC 80 Version 2.0 fuer ADM 31 Bildschirmsteuerung
; 28.07.89

	maclib Z80	; define Z80 op codes
	maclib ports	; define port addresses
	maclib modebaud	; define mode bits and baud equates


	public babinit,babout
	public csfabr,csrafr,csctrr,stfabr
	public zeisat

	extrn staon,staoff

;**************************************************************
; Vereinbarungen
;**************************************************************

tastp	equ 0ff80h
tastpe	equ 0ffbah

;**************************************************************
; Programm
;**************************************************************

	dseg
;	cseg

;**************** Initialisieren CRT-Steuerung ***************

babinit:
	di
	mvi a,17h ! sta csfabr ! out csfab
	rlc ! rlc ! rlc ! rlc
	sta csrafr ! out csraf
	xra a ! sta csctrr ! out csctr
	call staon
	lxi h,tastp		; clear coninbuffer
	mvi b,tastpe-tastp+1
sc1:	mvi m,0 ! inx h
	djnz sc1
	call staoff
	ei ! ret

	cseg

;**************************************************************
; BAB - output
;**************************************************************

babout:
	sspd consp			; save stack
	lxi sp,constk
	push psw ! lhld curs		; get cursor
	xra a ! sta curstp		; stop cursorset
	lda curmer ! ora a		; without cursor ?
	jrnz noclr
	lda cursta ! ora a		; reset cursor ?
	jrnz noclr			; --> no
	mov a,m ! xri 80h ! mov m,a	; reset cursor
	mvi a,0ffh ! sta cursta		; set cursor off
noclr:
	lda cupomer ! ora a		; position cursor ?
	jnz curpos1			; -> yes
	lda escmer ! add a		; get esccount * 2
	push b				; save character
	mvi b,0 ! mov c,a		; in BC
	lxi d,esc$jump$table		; jumptable
	xchg ! dad b			; in HL
	pop b				; get character
	mov a,m ! inx h ! mov h,m ! mov l,a	; drain in HL
	pchl				; and jump

esc$jump$table:
	dw noesc,esc$1byte,esc$2byte,esc$3byte
	dw esc$4byte,esc$5byte,esc$6byte

esc$2byte:
esc$3byte:
esc$4byte:
esc$5byte:
esc$6byte:
	xchg				; cursor in HL
conoerr:
cononul:
esc$end:
	xra a ! sta escmer ! jmp setcur

NOESC:
	xchg				; cursorposition in HL
	mov a,c ! cpi 7fh		; delete character
	jz crtcrtl			; -> yes
	cpi 20h				; controlcharacter ?
	jc crtcrtl			; -> yes
CRTZEI:					; output character
	mov b,a
	lda zeisat ! ora a		; change charactergenerator
	jz noums			; -> no
	mov a,b ! cpi 7eh
	jrz zeiums
	ani 0dfh ! cpi 5bh
	jrc noums
	cpi 5eh
	jrnc noums
zeiums:
	ani 1fh
	bit 5,b
	jrnz zeiums1
	sui 3
zeiums1:
	mov b,a
noums:
	lda invmer ! xra b ! mov m,a	; character to BAB
	call crtcri
SETCUR:
	lda curmer ! ora a		; set cursor ?
	jrnz noset			; -> no
	mvi a,2 ! sta curstp

; nachfolgende Routine mit Uhr verknuepfen

	xra	a
	sta	cursta
	mov	a,m
	xri	80h		; Setzen Cursor
	mov	m,a

;

noset:
	shld curs ! pop psw		; save cursorposition
	lspd consp			; get stackpointer
	ret

; Steuerzeichenauswertung 1. Byte
;_________________________________

CRTCRTL:
	lxi d,esc$end ! push d
	jz crtdch			; 7fh	
	xchg				; cursor in DE
	add a				; crtlchrar. * 2
	mvi b,0 ! mov c,a
	lxi h,esc$0werte		; jump table
	dad bc
	mov a,m ! inx h ! mov h,m ! mov l,a
	push h ! popiy			; drain in IY
	xchg				; cursor in HL
	pciy				; and jump

esc$0werte:
	dw	CONONUL		; 00h
	dw	CRTHOM		; 01h
	dw	CURSON		; 02h
	dw	CURSOF		; 03h
	dw	INVEON		; 04h
	dw	INVEOF		; 05h
	dw	conoerr		; 06h
	dw	conoerr		; 07h
	dw	CRTCLE		; 08h
	dw	conoerr		; 09h
	dw	CRTLF		; 0ah
	dw	conoerr		; 0bh
	dw	CRTFF		; 0ch
	dw	CRTCR		; 0dh
	dw	ascii		; 0eh
	dw	german		; 0fh
	dw	conoerr		; 10h
	dw	conoerr		; 11h
	dw	conoerr		; 12h
	dw	conoerr		; 13h
	dw	CRTDRB		; 14h
	dw	CRTCRI		; 15h
	dw	CRTDCZ		; 16h
	dw	CRTINL		; 17h
	dw	CRTDZE		; 18h
	dw	CRTDEL		; 19h
	dw	CRTCHO		; 1ah
	dw	CRTESC		; 1bh
	dw	conoerr		; 1ch
	dw	conoerr		; 1dh
	dw	conoerr		; 1eh
	dw	conoerr		; 1fh

; Auswertung 2. Byte der ESC - Folge
;____________________________________

esc$1byte:
	mov a,c ! cpi 80h
	jnc curposr
	lxi h,esc$end ! push h
	lxi	h,tab2wert
	lxi	b,tab2werte-tab2wert
	ccir			; Wert ermitteln
	slar	c		; Wert verdoppeln
	rlcr	b
	lxi	h,tab2sprung
	dad	bc		; und Tabellenwert dazu
	mov	a,m		; Zieladresse laden
	inx	h
	mov	h,m
	mov	l,a
	push	h
	popiy
	xchg			; Kursor nach HL
	pciy			; und Routine anspringen

tab2wert:
	db	57h,2ah,3ah,59h,79h,54h,74h,45h,52h,3dh,59h,29h,28h,27h,0
tab2werte:
tab2sprung:
	dw	conoerr		; 00h oder andere
	dw	cononul		; 27h
	dw	inveof		; 28h
	dw	inveon		; 29h
	dw	curpos		; 59h
	dw	curpos		; 3dh
	dw	crtdel		; 52h
	dw	crtinl		; 45h
	dw	crtdcz		; 74h
	dw	crtdcz		; 54h
	dw	crtdrb		; 79h
	dw	crtdrb		; 59h
	dw	crtff		; 3ah
	dw	crtff		; 2ah
	dw	crtdch		; 57h

; Kursorpositionierung
;______________________

curpos:
	pop d
	mvi a,20h ! sta curoffs
	mvi a,2 ! sta cupomer
	jmp noset
curposr:
	mvi a,80h ! sta curoffs
	mvi a,2
curpos1:
	dcr	a
	sta	cupomer
	jrz	curpos2
	LXI	H,0f800h	; Behandlung 1.Byte der Kursorpos.
	lda	curoffs
	mov	d,a
	MOV	A,C		; als Zeilenangabe
	sub	d		; minus Offset
	ORA	A
	jz noset
	CPI	18H
	JRC	ESC11
	jmp noset
ESC11:	MOV	B,A
	LXI	D,0050H
ESC12:	DAD	D
	DJNZ	ESC12
	jmp noset
curpos2:
	lda	curoffs
	mov	d,a
	MOV	A,C		; BEHANDLUNG 2.BYTE DER ESC-FO.
	sub	d		; ALS SPALTENANGABE
	CPI	50H
	LXI	D,004FH
	JRNC	ESC22
ESC21:	MOV	E,A
ESC22:	DAD	D
	jmp esc$end

CRTESC:	pop d
	lda escmer ! inr a ! sta escmer
	jmp noset

CRTDCH:	mvi	m,' '		; DEL
CRTCLE:	DCX	H		; BACKSPACE
	MOV	A,H
	CPI	0f7H
	RNZ
	INX	H
	RET
CRTFF:	LXI	H,0f800h		; FORM FEED
	LXI	D,0f801H
	LXI	B,077FH
	mvi	m,' '
	LDIR
CRTHOM:	LXI	H,0f800h		; HOME POSITION
	RET
CRTLF:	LXI	D,0050H		; LINE FEED
	DAD	D
	MOV	A,H
	CPI	0ffH
	RNZ
	MOV	A,L
	CPI	80H
	RC
	DSBC	DE		; SBC HL,DE
	JR	CRTPO1
CRTCRI:	INX	H		; NAECHSTE KURSORPOSITION
	MOV	A,H		; WENN NOETIG BILD ROLLEN
	CPI	0ffH
	RNZ
	MOV	A,L
	CPI	80H
	RC
	LXI	H,0ff30H
CRTPO1:	PUSH	H
	lxi	b,0730h
	LXI	H,0f850H
	LXI	D,0f800h
	lda	csctrr
	ori	2
	di
	out	csctr
	LDIR
	ani	0fdh
	out	csctr
	ei
	MVI	A,' '
	MVI	B,50H
CRTPO2:	DCX	H
	MOV	M,A
	DJNZ	CRTPO2
	POP	H
	RET
CRTCR:	MOV	B,H		; CARRIAGE RETURN
	MOV	C,L
	LXI	H,0ff7fH
	LXI	D,0050H
	ORA	A
CRTCR1:	DSBC	DE		; SBC HL,DE
	PUSH	H
	DSBC	BC		; SBC HL,BC
	POP	H
	JRNC	CRTCR1
	inx h
	RET
CRTDRB:	XCHG			; LOESCHEN AB CURSOR BIS
	LXI	H,0ff7FH		; BILDENDE
	DSBC	DE		; SBC HL,DE
crtdr0:	MOV	B,H
	MOV	C,L
CRTDR1:	MOV	H,D
	MOV	L,E
	INX	D
	MVI	M,' '
	LDIR
crtdr2:	LHLD	CURS
	RET
CRTDZE:	CALL	CRTCR		; LOESCHEN KURSORZEILE UND
				; SETZEN KURSOR AN ZEILEN-
				; ANFANG
CRTDCZ:				; LOESCHEN AB KURSORPOSITION    
                               	; BIS ZEILENENDE		
	push h ! call crtcr
	LXI D,0050H ! DAD D ! pop d ! push d ! ORA A
	DSBC DE
	jrz crtdc1
	dcx h
	call crtdr0		; Zeilenrest loeschen
crtdc1:	pop h ! ret		; wieder alter Kursor
CRTCHO:				; KURSOR EINE ZEILE HOCH
	LXI D,0050H
	DSBC DE
	mvi a,0f7h ! cmp h ! rc
	LHLD CURS ! RET
CRTINL:				; Insert line
				; at cursor position
	call crtcr
	push h			; begin of line
	lxi d,0ff30h
	xchg
	ora a
	dsbc de			; lenght
	jrz crtinl1		; last line
	mov b,h ! mov c,l
	lxi d,0ff7fh
	lxi h,0ff2fh
	lda csctrr ! ori 2
	di
	out csctr
	lddr
	ani 0fdh ! out csctr
	ei
crtinl1:
	pop h			; begin of line
	jmp crtdcz		; clear line
CRTDEL:				; Dellete line
				; at cursor position
	call crtcr
	push h			; begin of line
	lxi d,0ff30h
	xchg
	ora a
	dsbc de
	jrz crtdel1
	mov b,h ! mov c,l	; length
	pop d
	push d
	lxi h,50h
	dad d
	lda csctrr ! ori 2
	di
	out csctr
	ldir
	ani 0fdh ! out csctr
	ei
crtdel1:
	lxi h,0ff30h
	call crtdcz		; clear last line
	pop h
	ret
curson:
	xra a
cursof:
	sta curmer ! ret
inveof:
	xra a ! sta invmer ! ret
inveon:
	mvi a,80h ! sta invmer ! ret
ascii:
	xra a
german:
	sta zeisat ! ret
;farbaus:
;	xra	a
;	sta	escmer
;	mov	a,c
;	rlc ! rlc
;	bit 5,a
;	jrnz	noback
;	
;	jmp setcur

CURS:	DW	0f800h
ESCMER:	db	0
cupomer:
	db	0
curoffs:
	db	80h
curstp:	db	0
cursta:	db	0
curmer:	db	0
invmer:	db	0
zeisat:	db	0
csfabr:	db	0
csrafr:	db	0
csctrr:	db	0
stfabr:	db	07h


constak:
	ds	32
constk:
consp:	ds	2

	end
