	PAGE 85
	.Z80
	.XLIST
;-------------------------------------------------------
; CON1 - Video Treiber fuer ELZET 80 Video 80
;
; CON1  enthaelt  vier Einsprungstellen. Die erste
; dient zum Initialisieren aller Variablen und der
; Hardware (Einsprungpunkt CONINI). Dieser Schnittstelle
; werden keine Variablen uebergeben.
; Die zweite Schnittstelle, CONOUT, bekommt im C-Register 
; einen 7-Bit Binaerwert uebergeben. Jeder Wert im Bereich 
; 00H - 1FH wird als Steuerzeichen interpretiert. 
; Alle Zeichen im Bereich 20H - 7FH sind darstellbar und 
; werden im Video RAM abgelegt.
; CONIN und CONST sind gemaess CP/M-Konvention fuer
; die 20mA Schnittstelle der CPU/IEC-Karte definiert.
;
; VIDEO-80 gestattet neben dem Setzen und Zuruecksetzen
; der einzelnen Statusbits und dem Positionieren des
; Cursors den Aufbau von bis zu 8 verschiedenen Scroll-
; Windows. Mittels eines bestimmten Control Codes kann
; eines der Fenster adressiert werden. Alle weiteren
; Kommandos beziehen sich dann auf dieses Fenster. Dies
; gilt solange, bis ein anderes Scroll Window selektiert
; wird. Alle Steuerzeichen, die eine globale Wirkung
; haben, d.h. alle Positionen des physikalischen Video-
; speichers erreichen koennen, sind mit einem '*' ge-
; kennzeichnet. Werden nach einem Steuerzeichen Pa-
; rameter erwartet, so sind sie in geschweiften Klam-
; mern aufgefuehrt.
;
; Steuerzeichen:	8	Backspace		^H
;			9	Horizontal Tab		^I
;			A	Linefeed		^J
;			B	Vertical Tab		^K
;			C	Form Feed		^L
;			D	Carriage Return		^M
;
; Escape Sequenzen:	=	Set Cursor {X,Y}
;			A (*)	Cursor Type {T}
;			B	Set Window {N}
;			C	Set Window Margins
;				{X0,Y0,XM,YM}
;			D	Restore Status
;			E	Save Status
;			F	Set Cursor {Y,X}
;			G (*)	Erase Screen
;			H	Set Charset {N}
;			I	Clear Window
;			J	IV On
;			K	IV Off
;			L	INVIS On		(BLAU)
;			M	INVIS Off
;			N	PROT On			(GRUEN)
;			O	PROT Off
;			P	UNDERL On
;			Q	UNDERL Off
;			R	DIM On			(ROT)
;			S	DIM Off
;			T	BLINK On
;			U	BLINK Off
;			V	HOME
;			W	Status Line Enable
;			X	Status Line Disable
;			Y	Toggle Formfeed
;			Z	Erase End of Line
;			[	Erase End of Screen
;			\	Insert Line
;			]	Delete Line
;
; Die Felder auf dem Bildschirm werden durch die An-
; gabe der Eckkoordinaten definiert:
;
;	0				      79
;	-----------------------------------------
;     0	|					|
;	|					|
;	|	X0	       XM		|
;	|    Y0	.................		|
;	|    	.		.		|
;	|	.		.		|
;	|    YM	.................		|
;	|					|
;	|					|
;	|					|
;	|		.................	|
;	|		.		.	|
;	|		.................	|
;	|					|
;    24	-----------------------------------------
;
;-------------------------------------------------------
; Michael Bleistein			Revision 2.0
; Hoehenweg 80
; 3550 Marburg				Date: 07/02/84
;-------------------------------------------------------
	.LIST
	NAME	('CON1')
	TITLE	VIDEO-80 TREIBER FUER ELZET 80 VIDEO
	PUBLIC	CO1,INC1,CI1,CS1,INC1X
	EXTRN	CONST,NOSTAT,STON
;-------------------------------------------------------
	.XLIST
	;-----------------------------------------------
	; Einlesen der Bibliotheken
	;-----------------------------------------------
	INCLUDE	ASCII.LIB
	INCLUDE	ELZET.LIB
	INCLUDE	M6845.LIB
	;-----------------------------------------------
	; Konstantenvereinbarungen
	;-----------------------------------------------
MXESC	EQU	']'-'A'			
MAXFRM	EQU	8			
FRMLEN	EQU	9			
ERACHR	EQU	0			
RAMLEN	EQU	2048			
ATTOFF	EQU	RAMLEN/256		
	;-----------------------------------------------
	; Video Timing
	;-----------------------------------------------
HTC	EQU	120-1	;Anzahl der gesamten Zeichen
HLEN	EQU	16	;Start Sync-Impuls
HSYNC	EQU	9	;Laenge Sync-Impuls
VTC	EQU	27	;Anzahl der Zeilen
VADJ	EQU	0	;Adjust fuer Zeilen
SCALIN	EQU	12-1	;Anzahl der Zeilen pro Zeichen
CUSL	EQU	0	;Cursor Start
CUEL	EQU	12-1	;Cursor Ende
	;-----------------------------------------------
	; Bitpositionen der Attribute
	;-----------------------------------------------
UDL	EQU	7
INV	EQU	6
PRT	EQU	5
CH1	EQU	4
DIM	EQU	3
BLK	EQU	2
CH0	EQU	1
IVS	EQU	0
	;-----------------------------------------------
	; Cursor Definitionen
	;-----------------------------------------------
DEFCUR	EQU	?45B32 OR 0
CT0	EQU	0
CT1	EQU	1
CT2	EQU	2
TYP0	EQU	?45NOD
TYP1	EQU	?45B32 OR 11
TYP2	EQU	?45B32 OR 0
MXCUR	EQU	3
	;-----------------------------------------------
	; Relative Positionen der durch IY indizierten Variablen
	;-----------------------------------------------
CURL	EQU	0
CURH	EQU	1
ATT	EQU	2
X	EQU	3
Y	EQU	4
X0	EQU	5
XM	EQU	6
Y0	EQU	7
YM	EQU	8
	;-----------------------------------------------
	; Masken
	;-----------------------------------------------
WDWMSK	EQU	00000111B
ASCMSK	EQU	01111111B
CHRMSK	EQU	00000011B
CURMSK	EQU	00000111B
IOMASK	EQU	11111111B
TRUE	EQU	0FFH
	;-----------------------------------------------
	; SIO Definitionen
	;-----------------------------------------------
RD0	EQU	0
WR0	EQU	0
WR1	EQU	1
WR2	EQU	2
WR3	EQU	3
WR4	EQU	4
WR5	EQU	5
WR6	EQU	6
WR7	EQU	7
RXAV	EQU	0
;-------------------------------------------------------
	.LIST
	ORG 0EC0FH
;-------------------------------------------------------
; Unterprogramm CONINI
; CONINI initialisiert alle VIDEO-80 Hardware fuer
; Standard BAS Betrieb. Die Variablen des Video Trei-
; bers werden auf ihren Default Wert gesetzt.
; Dieses Unterprogramm initialisiert die Schnittstelle
; der CPU/IEC Karte.
;-------------------------------------------------------
INC1:	LD	B,SIOLEN
	LD	C,?CSBC
	LD	HL,SIOTAB
	OTIR
INC1X:	LD	A,(STON)
	LD	(STSAV),A
	LD	A,-1
	LD	(FFTOG),A
	;-----------------------------------------------
	; Hardware Initialisierung der MC 6845 Register.
	;-----------------------------------------------
	LD	HL,INITAB
	XOR	A
INI:	OUT	(?V8REG),A
	PUSH	AF
	LD	A,(HL)
	OUT	(?V8FIL),A
	POP	AF
	INC	A
	INC	HL
	CP	ITABL
	JR	NZ,INI
	;-----------------------------------------------
	; Initialisieren der Variablenbereiche
	; Die einzelnen Scroll Frames werden auf den
	; gesamten Bildschirmbereich gesetzt. Die Cur-
	; sorpositionen auf 'Home'.
	;-----------------------------------------------
	LD	B,MAXFRM
	LD	DE,VARBAS
	LD	(VARPTR),DE
IVLP:	PUSH	BC
	LD	HL,VARTAB
	LD	BC,VTABL
	LDIR
	POP	BC
	DJNZ	IVLP
	
	LD	A,DEFCUR
	LD	(SCURT),A
	CALL	SCRERA
	JP	FINI
	;-----------------------------------------------
	; Initialisierungstabelle INITAB
	; INITAB enthaelt die Initialisierungsbytes fuer 
	; den MC6845. Die Tabellenwerte sind fuer eine 
	; Video Taktfrequenz von 15 MHz gerechnet.
	;-----------------------------------------------
INITAB:	DB	HTC
	DB	?MXCOL
	DB	?MXCOL+HLEN
	DB	HSYNC
	DB	VTC
	DB	VADJ
	DB	?MXLIN
	DB	?MXLIN
	DB	?45NSM
	DB	SCALIN
	DB	?45B32 OR CUSL
	DB	CUEL
	DW	0
	DW	0
ITABL	EQU	$-INITAB
	;-----------------------------------------------
	; Die Tabelle SIOTAB enthaelt alle Kommandobytes
	; zur Initialisierung der SIO auf der CPU/IEC
	; Karte fuer den Betrieb als 8 Bit Serielle
	; Schnittstelle bei 9600 Baud.
	;-----------------------------------------------
SIOTAB:	DB	00011000B	;WR0 -> reset
	DB	WR1,00000000B	;WR1 -> No Interrupts	;
	DB	WR3,11000001B	;WR3 -> Rx Enable, 8 Bit;
	DB	WR4,11001100B	;WR4 -> x64 Clock,1 Stop;
	DB	WR5,11101010B	;WR5 -> TX 8 Bit	;
SIOLEN	EQU	$-SIOTAB
	;-----------------------------------------------
	; Initialisierungstabelle VARTAB
	; Vartab enthaelt die DEFAULT-Werte fuer jeden
	; der 8 Variablenframes der einzelnen Scroll-
	; Fenster.
	;-----------------------------------------------
VARTAB:	DW	?V8RAM
	DB	0
	DB	0
	DB	0
	DB	0
	DB	?MXCOL
	DB	0
	DB	?MXLIN
VTABL	EQU	$-VARTAB
;-------------------------------------------------------
; Unterprogramm CONIN
; Dieses Unterprogramm liest ein Zeichen von der Serien-
; schnittstelle. Ist kein Zeichen bereit, so wird gewartet.
;-------------------------------------------------------
CI1:	CALL	CONST
	AND	A
	JR	Z,CI1
	IN	A,(?CSBD)
	RET
;-------------------------------------------------------
; Unterprogramm CONST
; Das Unterprogramm CONST fragt den Status der Serien-
; schnittstelle ab. Im A Register wird bei vorhandenem
; Zeichen TRUE=FF uebergeben.
;-------------------------------------------------------
CS1:	IN	A,(?CSBC)
	BIT	RXAV,A
	LD	A,TRUE
	RET	NZ
	INC	A
	RET
;-------------------------------------------------------
; Unterprogramm CONOUT
; CONOUT wird mit einem 7 Bit Binaerwert im C Register
; aufgerufen. In Abhaengigkeit von vorausgegangenen Auf-
; rufen von CONOUT wird dann ueber den PC Pointer ENTRY
; verzweigt.
;-------------------------------------------------------
CO1:	LD	HL,(ENTRY)
	JP	(HL)
;-------------------------------------------------------
; Programmsegment BRANCH
; Ueber den Sprungvektor wird in allen Faellen, in denen
; keine Parameteruebergabe nach der Interpretation von
; Steuerzeichen zu erfolgen hat, BRANCH angesprungen.
; Hier wird zwischen darstellbaren Zeichen (Verzweigung
; nach PRINT) und Steuerzeichen (Table Lookup) unterschieden.
;-------------------------------------------------------
BRANCH:	LD	A,' '-1
	CP	C
	JP	C,PRINT
	
	LD	A,C
	AND	ASCMSK
	CP	?CR
	JP	Z,CR
	CP	?LF
	JP	Z,LF
	CP	?SUB
	JP	Z,FFSOFT
	CP	?BS
	JP	Z,BS
	CP	?ESC
	JR	Z,ESC
	CP	?HT
	JP	Z,DOTAB
	CP	?VT
	JP	Z,VT
	RET
;-------------------------------------------------------
; Programmsegment ESC
; ESC bearbeitet die definierten ESCAPE Sequenzen
; und steuert den Programmablauf entsprechend.
;-------------------------------------------------------
ESC:	LD	HL,DOESC
	LD	(ENTRY),HL
	LD	A,TRUE
	LD	(NOSTAT),A
	RET
	
DOESC:	LD	A,C
	CP	'='
	JP	Z,SETCUR
	SUB	'A'
	CP	MXESC+1
	JP	NC,FINI
	
	LD	C,A
	LD	HL,COMTAB
	LD	B,0
	ADD	HL,BC
	ADD	HL,BC
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	EX	DE,HL
	JP	(HL)
;-------------------------------------------------------
; Unterprogramm OFFS
; OFFS subtrahiert vom C Register 20H zum adjust fuer
; binaere Uebergaben.
;-------------------------------------------------------
OFFS:	PUSH	AF
	LD	A,C
	SUB	' '
	LD	C,A
	POP	AF
	RET
;-------------------------------------------------------
; Vektortabelle COMTAB
; COMTAB enthaelt alle Einsprungvektoren fuer die
; Ausfuehrung von Escape Sequenzen.
;-------------------------------------------------------
COMTAB:	DW	CURTYP
	DW	SETWDW
	DW	SETMRG
	DW	RCLSTA
	DW	STOSTA
	DW	SETCUR
	DW	SCRERA
	DW	CHRSET
	DW	FFWDW
	DW	IVSSET
	DW	IVSRES
	DW	INVSET
	DW	INVRES
	DW	PRTSET
	DW	PRTRES
	DW	UDLSET
	DW	UDLRES
	DW	DIMSET
	DW	DIMRES
	DW	BLKSET
	DW	BLKRES
	DW	HOME
	DW	ENSTA
	DW	DISSTA
	DW	FULLFF
	DW	ERAEOL
	DW	ERAEOS
	DW	INSLIN
	DW	DELLIN
;-------------------------------------------------------
; Unterprogramm LCPY
;-------------------------------------------------------
LCPY:	LD	B,0
	PUSH	BC
	PUSH	HL
	PUSH	DE
	CALL	VLDIR
	POP	DE
	POP	HL
	POP	BC
	LD	A,H
	SUB	ATTOFF
	LD	H,A
	LD	A,D
	SUB	ATTOFF
	LD	D,A
	JP	VLDIR
;-------------------------------------------------------
; Unterprogramm CPOS
;-------------------------------------------------------
CPOS:	PUSH	BC
	LD	A,E
	LD	HL,?V8RAM
	LD	BC,?MXCOL
	AND	A
ERAE1:	JR	Z,ERAE0
	ADD	HL,BC
	DEC	A
	JR	ERAE1		 
ERAE0:	LD	E,D
	LD	D,0
	ADD	HL,DE
	POP	BC
	RET
;-------------------------------------------------------
; Unterprogramm LERA
;-------------------------------------------------------
LERA:	LD	B,0
	LD	A,C
	AND	A
	RET	Z
	DEC	A
	RET	Z
	LD	C,A
	PUSH	BC
	PUSH	HL
	LD	E,L
	LD	D,H
	INC	DE
	LD	A,' '
	CALL	VPUTB
	LD	A,C
	AND	A
	JR	Z,LERA1
	CALL	VLDIR
LERA1:	POP	HL
	POP	BC
	LD	A,H
	SUB	ATTOFF
	LD	H,A
	LD	E,L
	LD	D,H
	INC	DE
	LD	A,000H
	CALL	VPUTB
	LD	A,C
	AND	A
	RET	Z
	JP	VLDIR
;-------------------------------------------------------
; Programmsegment ERAEOL
;-------------------------------------------------------
ERAEOL:	LD	IY,(VARPTR)
	LD	A,(IY+XM)
	SUB	(IY+X)
	LD	C,A
	LD	L,(IY+CURL)
	LD	H,(IY+CURH)
	CALL	LERA
	JP	FINI
;-------------------------------------------------------
; Programmsegment ERAEOS
;-------------------------------------------------------
ERAEOS:	LD	IY,(VARPTR)
	LD	A,(IY+XM)
	SUB	(IY+X)
	LD	C,A
	LD	L,(IY+CURL)
	LD	H,(IY+CURH)
	CALL	LERA
	
	LD	A,(IY+YM)
	SUB	(IY+Y)
	DEC	A
	JP	Z,FINI
	LD	B,A
	
	LD	D,(IY+X0)
	LD	E,(IY+Y)
	INC	E
	CALL	CPOS
	
	LD	A,(IY+XM)
	SUB	(IY+X0)
	LD	C,A
	
ERAE2:	PUSH	BC
	PUSH	HL
	CALL	LERA
	POP	HL
	LD	DE,?MXCOL
	ADD	HL,DE
	POP	BC
	DJNZ	ERAE2
	
	JP	FINI
;-------------------------------------------------------
; Programmsegment INSLIN
;-------------------------------------------------------
INSLIN:	LD	IY,(VARPTR)
	LD	A,(IY+YM)
	SUB	(IY+Y)
	DEC	A
	JR	Z,INSL0
	
	LD	B,A
	LD	D,(IY+X0)
	LD	E,(IY+YM)
	DEC	E
	CALL	CPOS
	
	LD	A,(IY+XM)
	SUB	(IY+X0)
	LD	C,A
	
INSL1:	PUSH	BC
	PUSH	HL
	LD	DE,-?MXCOL
	ADD	HL,DE
	POP	DE
	PUSH	HL
	CALL	LCPY
	POP	HL
	POP	BC
	DJNZ	INSL1
	
INSL0:	LD	D,(IY+X0)
	LD	E,(IY+Y)
	CALL	CPOS
	LD	A,(IY+XM)
	SUB	(IY+X0)
	LD	C,A
	CALL	LERA
	
	JP	FINI
;-------------------------------------------------------
; Programmsegment DELLIN
;-------------------------------------------------------
DELLIN:	LD	IY,(VARPTR)
	LD	A,(IY+YM)
	SUB	(IY+Y)
	DEC	A
	JR	Z,DELL0
	
	LD	B,A
	LD	D,(IY+X0)
	LD	E,(IY+Y)
	CALL	CPOS
	
	LD	A,(IY+XM)
	SUB	(IY+X0)
	LD	C,A
	
DELL1:	PUSH	BC
	PUSH	HL
	LD	DE,?MXCOL
	ADD	HL,DE
	POP	DE
	PUSH	HL
	CALL	LCPY
	POP	HL
	POP	BC
	DJNZ	DELL1
	
DELL0:	LD	D,(IY+X0)
	LD	E,(IY+YM)
	DEC	E
	CALL	CPOS
	LD	A,(IY+XM)
	SUB	(IY+X0)
	LD	C,A
	CALL	LERA
	
	JP	FINI
;-------------------------------------------------------
; Programmsegment PRINT
; PRINT wird direkt ueber BRANCH angesprungen. Es gibt
; das in C uebergebene Zeichen auf den Bildschirm aus.
; Dabei werden die Grenzen des lokalen Fensters einge-
; halten. Ist das Zeilenende erreicht, so wird in der
; nachfolgenden Zeile weiter geschrieben. Ist das untere
; Ende des Fensters erreicht, so wird der gesamte Bild
; schirminhalt nach oben geschoben. Bei allen Operationen
; wird zugleich im Zeichen- wie im Statusbereich gearbeitet.
; Vor allen Video Operationen wird ueber den Port ?V8TOG
; das Video Ram eingeblendet.
;-------------------------------------------------------
PRINT:	LD	IY,(VARPTR)
	;-----------------------------------------------
	; Das IY Register wird mit dem Variablen Pointer
	; VARPTR geladen. Dann wird in die von CUR..
	; adressierte Speicherstelle das Zeichen aus
	; C geschrieben. Mit entsprechendem Offset
	; wird auch das zugeordnete Statusbyte mit dem
	; Frame-spezifischen Default geladen.
	;-----------------------------------------------
	LD	H,(IY+CURH)
	LD	L,(IY+CURL)
	LD	A,C
	AND	ASCMSK
	BIT	IVS,(IY+ATT)
	JR	Z,NOTINV
	OR	NOT ASCMSK
NOTINV:	CALL	VPUTB
	LD	A,H
	SUB	ATTOFF
	LD	D,A
	LD	E,L
	LD	A,(IY+ATT)
	EX	DE,HL
	CALL	VPUTB
	EX	DE,HL
	INC	HL
	;-----------------------------------------------
	; HL enthaelt die naechste Position im Video
	; Speicher. Jetzt wird getestet, ob das Zeilen-
	; ende erreicht ist.
	;-----------------------------------------------
FORWAR:	LD	A,(IY+X)
	INC	A
	CP	(IY+XM)
	JP	C,XOK
	;-----------------------------------------------
	; Das Zeilenende ist erreicht. Es wird getestet,
	; ob das untere Ende des Frames erreicht wurde.
	;-----------------------------------------------
LFX:	LD	A,(IY+Y)
	INC	A
	CP	(IY+YM)
	JR	C,YOK0
	;-----------------------------------------------
	; Das untere Ende des Fensters ist erreicht. Der
	; Inhalt des gesamten Frames wird um eine Zeile
	; nach oben geschoben. Die erste Zeile geht ver-
	; loren, die letzte wird mit 00H neu initialisiert.
	;-----------------------------------------------
	LD	HL,?S8RAM
	CALL	SCROLL
	LD	HL,?V8RAM
	CALL	SCROLL
	
	LD	A,(IY+X0)
	LD	(IY+X),A
	LD	A,(IY+YM)
	DEC	A
	;-----------------------------------------------
	; Der Zeilenzaehler wird mit dem Inhalt des
	; A Registers gesetzt. Dann wird im HL Register
	; die neue Cursorposition errechnet. Das A Re-
	; gister wird mit dem neuen Spaltenzaehler
	; geladen.
	;-----------------------------------------------
YOK:	LD	(IY+Y),A
	
	LD	HL,?V8RAM
	LD	DE,?MXCOL
	AND	A
YLP:	JR	Z,YLPE
	ADD	HL,DE
	DEC	A
	JP	YLP
YLPE:	LD	E,(IY+X)
	LD	D,0
	ADD	HL,DE
	
	LD	A,E
	;-----------------------------------------------
	; Setzen des Spaltenzaehlers. Danach wird das
	; Cursor Register gesetzt und zum Setzen des
	; Hardwarecursors 'durch gefallen'.
	;-----------------------------------------------
XOK:	LD	(IY+X),A
	LD	(IY+CURH),H
	LD	(IY+CURL),L
	;-----------------------------------------------
	; Programmsegment OUTCUR
	; Setzen des Cursors in die Hardware Register
	; des 6845 Steuerbausteins.
	;-----------------------------------------------
OUTCUR:	LD	A,?45CUH
	OUT	(?V8REG),A
	LD	A,H
	AND	CURMSK
	OUT	(?V8FIL),A
	LD	A,?45CUL
	OUT	(?V8REG),A
	LD	A,L
	OUT	(?V8FIL),A
	RET
	;-----------------------------------------------
	; Programmsegment YOK0
	; Start bei Spalte 1 der naechsten Zeile.
	;-----------------------------------------------
YOK0:	LD	B,(IY+X0)
	LD	(IY+X),B
	JR	YOK
;-------------------------------------------------------
; Unterprogramm SCROLL
; SCROLL wird mit der Basisadresse des Video Bereichs
; im HL Register aufgerufen. Danach wird der lokale
; Bereich eines einzelnen Fensters gescrollt.
;-------------------------------------------------------
SCROLL:	LD	A,(IY+Y0)
	LD	DE,?MXCOL
	AND	A
SLP:	JR	Z,SLPE
	ADD	HL,DE
	DEC	A
	JP	SLP
	
SLPE:	LD	E,(IY+X0)
	LD	D,0
	ADD	HL,DE
	;-----------------------------------------------
	; Der Inhalt des HL Register ist ein Pointer
	; auf die erste Adresse des selektierten Fensters.
	; Das HL Register wird auf die Position des
	; letzten Zeichens der folgenden (virtuellen)
	; Zeile gesetzt.
	; Das A Register wird mit der Zeilenzahl-1 und
	; das C Register mit der Spaltenzahl des Fen-
	; sters geladen.
	;-----------------------------------------------
	LD	A,(IY+XM)
	SUB	(IY+X0)
	LD	C,A
	LD	B,0
	
	LD	A,(IY+YM)
	SUB	(IY+Y0)
	JR	Z,SCRLPD
	DEC	A
	;-----------------------------------------------
	; Die Scrollschleife besteht aus 2 verschachtel-
	; ten Schleifen, die im Video Ram Speicherzellen
	; umkopieren. Durch alternierende Verwendung von
	; LDDR und LDIR wird die Pointerarithmetik ver-
	; einfacht.
	;-----------------------------------------------
SCRLP:	PUSH	HL
	LD	DE,?MXCOL
	ADD	HL,DE
	POP	DE
	
	PUSH	BC
	CALL	VLDIR
	POP	BC
	
	DEC	HL
	DEC	DE
	
	DEC	A
	JR	Z,SCRLPE
	
	PUSH	HL
	LD	DE,?MXCOL
	ADD	HL,DE
	POP	DE
	
	PUSH	BC
	CALL	VLDDR
	POP	BC
	
	INC	HL
	INC	DE
	
	DEC	A
	JR	NZ,SCRLP
	;-----------------------------------------------
	; Loeschen der letzten Zeile. Die Speicherin-
	; halte der letzten Zeile werden mit 00H ueber-
	; schrieben. Damit kann SCROLL sowohl zum Ver-
	; schieben des Zeichen- wie des Attributspei-
	; chers verwendet werden.
	;-----------------------------------------------
SCRLPD:	DEC	BC
	LD	D,H
	LD	E,L
	INC	DE
	LD	A,ERACHR
	CALL	VPUTB
	CALL	VLDIR
	RET
	
SCRLPE:	DEC	BC
	LD	D,H
	LD	E,L
	DEC	DE
	LD	A,ERACHR
	CALL	VPUTB
	CALL	VLDDR
	RET
;-------------------------------------------------------
; Programmsegment CURTYP
; Setzen des Hardware Cursor Typs. Dem Aufruf folgt die 
; Uebergabe eines Parameters P.
; P:	0 --->	Cursor Off
; 	1 --->	Blink Line
;	2 --->	Blink Block
;-------------------------------------------------------
CURTYP:	LD	HL,TYPCUR
	LD	(ENTRY),HL
	RET
	
TYPCUR:	CALL	OFFS
	LD	A,C
	CP	MXCUR
	JP	NC,FINI
	LD	(CURT),A
	
	CP	CT0
	JR	Z,SET0
	CP	CT1
	JR	Z,SET1
	
SET2:	LD	B,TYP2
	JR	SETC
SET1:	LD	B,TYP1
	JR	SETC
SET0:	LD	B,TYP0
	
SETC:	LD	A,?45CS
	OUT	(?V8REG),A
	LD	A,B
	OUT	(?V8FIL),A
	
	JP	FINI
;-------------------------------------------------------
; Programmsegment SETWDW
; SETWDW setzt den Variablenpointer VARPTR auf das ange-
; waehlte Fenster. Es sind 8 Fenster definierbar. Da der
; Parameter maskiert wird, wird er modulo 8 interpretiert.
;-------------------------------------------------------
SETWDW:	LD	HL,WDWSET
	LD	(ENTRY),HL
	RET
	
WDWSET:	CALL	OFFS
	LD	A,WDWMSK
	AND	C
	LD	HL,VARBAS
	LD	DE,FRMLEN
WDLP:	JR	Z,WDLPE
	ADD	HL,DE
	DEC	A
	JR	WDLP
WDLPE:	LD	(VARPTR),HL
	LD	IY,(VARPTR)
	JP	SETC1E
;-------------------------------------------------------
; Programmsegment SETMRG
; SETMRG setzt die kartesischen Begrenzungen des selek-
; tierten Scroll Feldes. Es werden die 4 Parameter
; X0, Y0, XM und YM in der gegebenen Reihenfolge erwartet.
;-------------------------------------------------------
SETMRG:	LD	HL,MRG1
	LD	(ENTRY),HL
	RET
	
MRG1:	CALL	OFFS
	LD	IY,(VARPTR)
	LD	A,?MXCOL
	CP	C
	JR	C,MRGN1
	LD	(IY+X0),C
MRGN1:	LD	HL,MRG2
	LD	(ENTRY),HL
	RET
	
MRG2:	CALL	OFFS
	LD	IY,(VARPTR)
	LD	A,?MXLIN
	CP	C
	JR	C,MRGN2
	LD	(IY+Y0),C
MRGN2:	LD	HL,MRG3
	LD	(ENTRY),HL
	RET
	
MRG3:	CALL	OFFS
	LD	IY,(VARPTR)
	LD	A,(IY+X0)
	CP	C
	JR	C,MRGS3
	INC	A
	LD	(IY+XM),A
	JR	MRGN3
MRGS3:	INC	C
	LD	A,?MXCOL
	CP	C
	JR	NC,MRG3ST
	LD	C,A
MRG3ST:	LD	(IY+XM),C
MRGN3:	LD	HL,MRG4
	LD	(ENTRY),HL
	RET
	
MRG4:	CALL	OFFS
	LD	IY,(VARPTR)
	LD	A,(IY+X0)	; <-- Hier ist der Fehler: X0 statt Y0 !!
	CP	C
	JR	C,MRGS4
	INC	A
	LD	(IY+YM),A
	JR	MRG5
MRGS4:	INC	C
	LD	A,?MXLIN
	CP	C
	JR	NC,MRG4ST
	LD	C,A
MRG4ST:	LD	(IY+YM),C
	
MRG5:	LD	A,(IY+X0)
	LD	(IY+X),A
	LD	A,(IY+Y0)
	LD	(IY+Y),A
	CALL	SETC1E 		;<-- ...und hier kann es JP SETC1E heissen.
	JP	FINI
;-------------------------------------------------------
; Programmsegment STOSTA
; STOSTA erwartet keine Parameter. Durch STOSTA wird der
; gesamte Status des selektierten Fensters gespeichert.
;-------------------------------------------------------
STOSTA:	LD	HL,(VARPTR)
	LD	(SVARP),HL
	LD	A,(CURT)
	LD	(SCURT),A
	JP	FINI
;-------------------------------------------------------
; Programmsegment RCLSTA
; RCLSTA belegt die Register des adressierten Fensters
; mit den mit STOSTA abgespeicherten Werten.
;-------------------------------------------------------
RCLSTA:	LD	HL,(SVARP)
	LD	(VARPTR),HL
	PUSH	HL
	POP	IY
	LD	H,(IY+CURH)
	LD	L,(IY+CURL)
	CALL	OUTCUR
	LD	A,(SCURT)
	LD	(CURT),A
	ADD	A,020H
	JP	TYPCUR
;-------------------------------------------------------
; Programmsegment SETCUR
; SETCUR setzt den Cursor auf die in den beiden nach-
; folgenden Parametern angegebene Position. Diese Po-
; sition ist relativ zur linken oberen Ecke eines Scroll-
; Fensters. Ist eine absolute Adressierung auf dem
; Schirm gewuenscht, empfiehlt es sich, das Fenster 0
; entsprechend (0,0,80,25) zu calibrieren.
; SETCUR prueft, ob die Cursorposition innerhalb des
; selektierten Frames liegt. Wird eine Adressierung
; ausserhalb des Frames durchgefuehrt, bleibt die
; bisherige Position erhalten.
; Nach dem Setzen des Cursors wird das Cursor Re-
; gister des Frames neu berechnet.
;-------------------------------------------------------
SETCUR:	LD	HL,SETC2
	LD	(ENTRY),HL
	RET
	
SETC1:	CALL	OFFS
	LD	IY,(VARPTR)
	LD	A,(IY+X0)
	CP	C
	JR	Z,SETC1O
	JR	NC,SETC1E
SETC1O:	ADD	A,C
	LD	C,A
	LD	A,(IY+XM)
	CP	C
	JR	C,SETC1E
	JR	Z,SETC1E
	LD	(IY+X),C
SETC1E:	LD	A,(IY+Y)
	CALL	YOK
	JP	FINI
	
SETC2:	CALL	OFFS
	LD	IY,(VARPTR)
	LD	A,(IY+Y0)
	CP	C
	JR	Z,SETC2O
	JR	NC,SETC2E
SETC2O:	ADD	A,C
	LD	C,A
	LD	A,(IY+YM)
	CP	C
	JR	C,SETC2E
	JR	Z,SETC2E
	LD	(IY+Y),C
SETC2E:	LD	HL,SETC1
	LD	(ENTRY),HL
	RET
;-------------------------------------------------------
; Programmsegment HOME
; HOME steuert die obere, linke Position im Frame an.
;-------------------------------------------------------
HOME:	LD	IY,(VARPTR)
	LD	A,(IY+X0)
	LD	(IY+X),A
	LD	A,(IY+Y0)
	CALL	YOK
	JP	FINI
;-------------------------------------------------------
; Programmsegment SCRERA
; SCRERA loescht den gesamten Zeichen und Attributspei-
; cher auf den Wert 00H. Die einzelnen Frames bleiben
; dabei ebenso wie die augenblickliche Cursorposition
; erhalten.
;-------------------------------------------------------
SCRERA:	LD	HL,?S8RAM
	LD	DE,?S8RAM+1
	LD	BC,2*RAMLEN-1
	LD	A,ERACHR
	CALL	VPUTB
	CALL	VLDIR
	JP	FINI
;-------------------------------------------------------
; Programmsegment BS
; BS steuert den Cursor rueckwaerts. Dabei wird analog
; der Routine PRINT gearbeitet. Allerdings wird beim
; Erreichen der oberen Frame-Grenze keine Scroll-Oper-
; ation durchgefuehrt.
;-------------------------------------------------------
BS:	LD	IY,(VARPTR)
	LD	A,(IY+X)
	CP	(IY+X0)
	JR	Z,OVL
	
	DEC	A
	LD	(IY+X),A
	LD	A,(IY+Y)
	JP	YOK
	
OVL:	LD	A,(IY+Y)
	CP	(IY+Y0)
	JP	Z,FINI
	
	DEC	A
	LD	B,(IY+XM)
	DEC	B
	LD	(IY+X),B
	JP	YOK
;-------------------------------------------------------
; Programmsegment CHRSET
; CHRSET erwartet einen Parameter. Der Wert des Para-
; meters wird in die Zeichensatz-Bits der ATT Variable
; kopiert. Der Parameter wird Modulo 4 interpretiert.
;-------------------------------------------------------
CHRSET:	LD	HL,SETCHR
	LD	(ENTRY),HL
	RET
	
SETCHR:	CALL	OFFS
	LD	IY,(VARPTR)
	BIT	0,C
	JR	NZ,NOS1
	RES	CH0,(IY+ATT)
	JR	NOS2
NOS1:	SET	CH0,(IY+ATT)
NOS2:	BIT	1,C
	JR	NZ,NOS3
	RES	CH1,(IY+ATT)
	JR	NOS4
NOS3:	SET	CH1,(IY+ATT)
NOS4:	JP	FINI
;-------------------------------------------------------
; Programmsegment VT
; VT setzt die Cursor Variablen auf die vorige Zeile.
;-------------------------------------------------------
VT:	LD	IY,(VARPTR)
	LD	A,(IY+Y)
	DEC	A
	JP	M,FINI
	CP	(IY+Y0)
	JP	C,FINI
	JP	YOK
;-------------------------------------------------------
; Programmsegment LF
; LF setzt die Cursor Variablen auf die naechste Zeile.
;-------------------------------------------------------
LF:	LD	IY,(VARPTR)
	LD	A,(IY+Y)
	INC	A
	CP	(IY+YM)
	JP	C,YOK
	;-----------------------------------------------
	; Das untere Ende des Fensters ist erreicht. Der
	; Inhalt des gesamten Frames wird um eine Zeile
	; nach oben geschoben. Die erste Zeile geht ver-
	; loren, die letzte wird mit 00H neu initialisiert.
	;-----------------------------------------------
	LD	HL,?S8RAM
	CALL	SCROLL
	LD	HL,?V8RAM
	CALL	SCROLL
	
	LD	A,(IY+YM)
	DEC	A
	JP	YOK
;-------------------------------------------------------
; Programmsegment FFWDW
; FFWDW loescht alle Variablen und Statuswerte innerhalb
; eines Frames. Der Cursor wird in der linken oberen
; Ecke positioniert.
;-------------------------------------------------------
FFWDW:	LD	IY,(VARPTR)
	LD	HL,?V8RAM
	CALL	ERAS
	LD	HL,?S8RAM
	CALL	ERAS
	
	LD	A,(IY+X0)
	LD	(IY+X),A
	LD	A,(IY+Y0)
	CALL	YOK
	JP	FINI
;-------------------------------------------------------
; Unterprogramm ERAS
; ERAS wird von FFWDW aufgerufen und loescht einen
; Bildschirmbereich. Im HL Register wird die Basis-
; adresse dieses Bereichs uebergeben.
; Registerbelegung:	A	Zeilenzaehler
;			BC	Spaltenzaehler
;			HL,DE	Transfer Pointer
;-------------------------------------------------------
ERAS:	LD	A,(IY+YM)
	DEC	A
	LD	DE,?MXCOL
	;-----------------------------------------------
	; Die Endposition des Loeschbereiches wird er-
	; rechnet (mit Offset ?MXCOL).
	;-----------------------------------------------
ERLP:	JR	Z,ERLPE
	ADD	HL,DE
	DEC	A
	JP	ERLP
ERLPE:	LD	E,(IY+XM)
	DEC	E
	LD	D,0
	ADD	HL,DE
	;-----------------------------------------------
	; Das BC Register wird mit der Zeilenlaenge
	; des Fensters geladen. Im A Register wird die
	; Anzahl der Zeilen gespeichert.
	;-----------------------------------------------
	LD	A,(IY+XM)
	SUB	(IY+X0)
	DEC	A
	LD	C,A
	LD	B,0
	LD	A,(IY+YM)
	SUB	(IY+Y0)
	;-----------------------------------------------
	; Die Loeschschleife. Durch alternierende Ver-
	; wendung von LDIR und LDDR Befehlen wird die
	; Pointerarithmetik stark vereinfacht.
	;-----------------------------------------------
ERA00:	LD	E,L
	LD	D,H
	DEC	DE
	PUSH	BC
	PUSH	AF
	LD	A,ERACHR
	CALL	VPUTB
	CALL	VLDDR
	POP	AF
	POP	BC
	DEC	A
	RET	Z
	LD	DE,-?MXCOL
	ADD	HL,DE
	LD	E,L
	LD	D,H
	INC	DE
	PUSH	BC
	PUSH	AF
	LD	A,ERACHR
	CALL	VPUTB
	CALL	VLDIR
	POP	AF
	POP	BC
	LD	DE,-?MXCOL
	ADD	HL,DE
	DEC	A
	JP	NZ,ERA00
	RET
;-------------------------------------------------------
; Programmsegment ENSTA
;-------------------------------------------------------
ENSTA:	LD	A,(STSAV)
	LD	(STON),A
	JP	FINI
;-------------------------------------------------------
; Programmsegment DISSTA
;-------------------------------------------------------
DISSTA:	XOR	A
	LD	(STON),A
	JP	FINI
;-------------------------------------------------------
; Programmsegment FULLFF
;-------------------------------------------------------
FULLFF:	LD	A,(FFTOG)
	CPL
	LD	(FFTOG),A
	JP	FINI
;-------------------------------------------------------
; Programmsegment FFSOFT
; FFSOFT fuehrt 4 LF Sequenzen durch. Da das Steuer-
; zeichen 'Form Feed' interpretiert wird, sind Pro-
; grammausgaben auf den Drucker besser zu verfolgen,
; da das ploetzliche Loeschen des Bildschirms ver-
; mieden wird.
;-------------------------------------------------------
FFSOFT:	LD	A,(FFTOG)
	AND	A
	JP	NZ,FFWDW
	
	LD	IY,(VARPTR)
	CALL	LFX
	CALL	LFX
	CALL	LFX
	JP	LFX
;-------------------------------------------------------
; Programmsegment CR
; CR positioniert den Cursor an den linken Rand eines
; Frames. Dazu werden die entsprechenden Cursor Re-
; gister geladen.
;-------------------------------------------------------
CR:	LD	IY,(VARPTR)
	LD	A,(IY+X0)
	LD	(IY+X),A
	LD	A,(IY+Y)
	JP	YOK
;-------------------------------------------------------
; Programmsegment DOTAB
;-------------------------------------------------------
DOTAB:	LD	IY,(VARPTR)
	LD	H,(IY+CURH)
	LD	L,(IY+CURL)
	INC	HL
	JP	FORWAR
;-------------------------------------------------------
; Programmsegment ..ON und ..OFF
; Diese Routinen setzen bzw. loeschen die einzelnen
; Attribute in der ATT Variable des adressierten Frames.
;
; Attributbelegung der Variablenbit's:
; -------------------------------------------------
; | XXX | INV | PRT | UDL | DIM | BLK | XXX | IVS |
; -------------------------------------------------
;
; Die mit XXX belegten Positionen sind fuer die Se-
; lektion des Zeichensatzes vorgesehen.
;
; IVS	Invers Video
; INV	Invisible
; PRT	Protected
; UDL	Underlined
; DIM	Half Intensity
; BLK	Blink
;-------------------------------------------------------
IVSSET:	LD	IY,(VARPTR)
	SET	IVS,(IY+ATT)
	JR	FINI
IVSRES:	LD	IY,(VARPTR)
	RES	IVS,(IY+ATT)
	JR	FINI
INVSET:	LD	IY,(VARPTR)
	SET	INV,(IY+ATT)
	JR	FINI
INVRES:	LD	IY,(VARPTR)
	RES	INV,(IY+ATT)
	JR	FINI
PRTSET:	LD	IY,(VARPTR)
	SET	PRT,(IY+ATT)
	JR	FINI
PRTRES:	LD	IY,(VARPTR)
	RES	PRT,(IY+ATT)
	JR	FINI
UDLSET:	LD	IY,(VARPTR)
	SET	UDL,(IY+ATT)
	JR	FINI
UDLRES:	LD	IY,(VARPTR)
	RES	UDL,(IY+ATT)
	JR	FINI
DIMSET:	LD	IY,(VARPTR)
	SET	DIM,(IY+ATT)
	JR	FINI
DIMRES:	LD	IY,(VARPTR)
	RES	DIM,(IY+ATT)
	JR	FINI
BLKSET:	LD	IY,(VARPTR)
	SET	BLK,(IY+ATT)
	JR	FINI
BLKRES:	LD	IY,(VARPTR)
	RES	BLK,(IY+ATT)
	JR	FINI
;-------------------------------------------------------
; Programmsegment FINI
; FINI setzt vor dem Ruecksprung den ENTRY Pointer auf BRANCH
;-------------------------------------------------------
FINI:	LD	HL,BRANCH
	LD	(ENTRY),HL
	XOR	A
	LD	(NOSTAT),A
	RET
;-------------------------------------------------------
; Variablen
;-------------------------------------------------------
	DSEG
STSAV:	DEFS	1
FFTOG:	DEFS	1
CURT:	DEFS	1
SVARP:	DEFS	2
SCURT:	DEFS	1
VARPTR:	DEFS	2
ENTRY:	DEFS	2
VARBAS:	DEFS	MAXFRM*FRMLEN
;-------------------------------------------------------
	END
