	.PREL
	.IDENT	CHAR
	.INSERT	HVG.LIB
	.INSERT	MACRO.LIB
	.INSERT	BBEQU.ASM
	.RELOC
; SOME SLEAZY EQUATES
WXR=0	; WINDOW FELLAS
WXL=2
WYU=4
WYL=6
BACKUP=8	; CONTROL H MEANS BACK UP 1 CHAR
; TABLE GIVING ASCII CHARS FOR TOKENS
TOKTXT:	
	.ASCII	   'LIS'
	.BYTE	'T'+80H
	.ASCII	   'CLEA'
	.BYTE	'R'+80H
	.ASCII	   'RU'
	.BYTE	'N'+80H
	.ASCII	   'NEX'
	.BYTE	'T'+80H
	.ASCII	   'LIN'
	.BYTE	'E'+80H
	.BYTE	'I'
	.BYTE	'F'+80H
	.ASCII	   'GOT'
	.BYTE	'O'+80H
	.ASCII	   'GOSU'
	.BYTE	'B'+80H
	.ASCII	   'RETUR'
	.BYTE	'N'+80H
	.ASCII	   'BO'
	.BYTE	'X'+80H
	.ASCII	   'FO'
	.BYTE	'R'+80H
	.ASCII	   'INPU'
	.BYTE	'T'+80H
	.ASCII	   'PRIN'
	.BYTE	'T'+80H
	.ASCII	   'STE'
	.BYTE	'P'+80H
	.ASCII	   'RN'
	.BYTE	'D'+80H
	.BYTE	'T'
	.BYTE	'O'+80H
	.ASCIS	'DATA'
	.ASCIS	'CIRCLE'
	.ASCIS	'POINT'
	.ASCIS	'DEFAULT'
	.ASCIS	'SHOW'
	.ASCIS	'SNAP'
	.ASCIS	'ZERO'
	.ASCIS	'SCROLL'
; FUNCTION TO RETURN FONT DESCRIPTOR ADDRESS FOR SMALL FONT
SMALF::	LXI	H,SMLFNT
	RET
; SIMILAR FUNCTION FOR LARGE FONT DESCRIPTOR
LARGEF:: LXI	H,LRGFNT#
	RET
; DEVICE VARIABLE TO OUTPUT CHARACTER ON VDM
PUTCD::	TSTC    '=',PUTCD2
	RSTEXP
	MOV	A,L
	RSTOCH
	RSTFIN
PUTCD2:	JMP	QWHAT#
CRLF::	MVI	A,CR
; OUTPUT CHARACTER ROUTINE
OUTCLA:: PUSH	H
	PUSH	D
	PUSH	B
	PUSH	PSW
	MOV	D,A
	CALL	TOUTCK#	; CHECK FOR TAPE OUTPUT
VDMCAL:	MOV	A,D
	STA	VDMLC#
	CALL	VDM
	POP	PSW
	POP	B
	POP	D
	POP	H
	RET
; ROUTINE TO DISPLAY A TOKEN IN FULL FORM
TOKEP:	CALL	TOKEPT
TOKEP1:	MOV	A,M
	ANI	7FH
	PUSH	H
	CALL	VDMTOK
	POP	H
	MOV	A,M
	INX	H
	RLC	
	JRNC	TOKEP1
TOKEP2:	MVI	A,' '	; PUT SPACE AFTER TOKEN
	JMPR	VDMTOK	; AND WANDER BACK
; SUBROUTINE TO POINT AT STRING FOR TOKEN
TOKEPT:: LXI	H,TOKTXT	; POINT AT LIST
	SUI	68H
JOKEP1:	RZ
JOKEP2:	BIT	7,M	; MOVE PAST NEXT WORD
	INX	H
	JRZ	JOKEP2
	DCR	A
	JMPR	JOKEP1
SMLFNT:: .BYTE	20H
	.BYTE	3,5,4,6
	.WORD	FNT35
; *****
; *
; * CHARACTER DISPLAY ROUTINE
; *
; *****
; DEVICE VARIABLE OFFSETS
CF.X=0
CF.Y=2
CF.M=4
CF.C=6
CF.F=8
; FIELDS IN FONT DESCRIPTOR
FD.BASE=0
FD.XCS=1
FD.YCS=2
FD.XF=3
FD.YF=4
FD.AD=5
FD.FLG=7
; ENTRY FOR TOKEN PRINTING
VDMTOK:	MOV	L,A
	LDA	TAPEST#
	CPI	6
	MOV	A,L
	JRZ	OUTCLA
; SOME CLOWNS COME IN HERE
VDM::
	PUSH	X
	PUSH	Y
	LHLD	WINPTR#		; FIX WINDOW PTR
	PUSH	H
	LXI	H,VDMCR#
	SHLD	WINPTR#
	LXI	Y,VDMX#	; POINT AT DEVICES
	LIXD	VDMCF#		; IX= CHAR FONT
	CPI	CR
	JRNZ	..NONL
; NEW LINE CASE
	CALL	RESCX		; RESET CX
	CALL	CYSCROLL	; SCROLL IF CY IS OFFSCREEN
	CALL	BUMPCY		; ADVANCE CY
	JMPR	..DONE
..NONL:
	CPI	RUBOUT		; HOW ABOUT RUBOUT ?
	JRNZ	..NORB		; JUMP IF NOT HIM
; WE GOT THE RUBOUT KEY FOLKS
	MVI	A,BACKUP	; BACKUP
	CALL	VDM
	MVI	A,' '		; ERASE PREVIOUS FELLA
	CALL	VDM
	MVI	A,BACKUP	; THEN BACK UP AGAIN!
..NORB:
	CPI	BACKUP		; HOW ABOUT BACKUP KEY?
	JRNZ	..NBKU
	CALL	LEFTX		; MOVE CX LEFT
	CALL	XCHECK
	JRNC	..DONE		; JUMP IF OK
	CALL	UPY		; ELSE BACK UP Y
	CALL	FINDLAST ; FIND LAST CHAR POS ON PREV LINE
	JMPR	..DONE
; CHECK FOR TOKEN
..NBKU:
	CPI	68H
	JRC	..NTOK
	CPI	80H
	JRNC	..FLK	; IF >80 ITS A FLAKE
	CALL	TOKEP	; PRINT THE TOKEN
	JMPR	..DONE	; THEN GO HOME
..NTOK:	CPI	' '	; CONTROL CHARS TO ?
	JRNC	..COK
..FLK:	MVI	A,'?'		; FLAKE CHAR - MAKE A ?
..COK:
	CALL	PNOTE#		; PLAY A NOTE
	PUSH	PSW
	CALL	XCHECK		; IS X OFFSCREEN
	JRNC	..XON
	CALL	RESCX		; RESET CX
	CALL	CYTOPCK		; CHECK FOR CY ABOVE TOP
	CALL	BUMPCY		; ADVANCE CY
..XON:
	CALL	CYSCROLL	; SCROLL IF CY NEEDS IT
	POP	PSW
	CALL	DCHAR		; BUG CHARACTER DISPLAYER
	CALL	BUMPCX		; ADVANCE CX
..DONE:
	POP	H
	SHLD	WINPTR#
	POP	Y
	POP	X
	RET
; SUBROUTINE TO DISPLAY CHARACTER ON THE SCREEN
DCHAR:
; FIRST DRAW BOX TO ERASE
	PUSH	PSW
	MVI	A,4	; ERASETH
	BIT	2,CF.M(Y)	; SHOULD WE GHOST THE CHARACTER?
	CNZ	CALBOX		; ONLY IF PLOP OPTION
; PERFORM PATTERN LOOKUP
	POP	PSW		; A=CHAR
..NOTC:	SUB	FD.BASE(X)
	MOV	E,A
	MOV	A,CF.M(Y)
	RLC
	RLC
	OUT	XPAND
	MVI	D,0
	MOV	A,FD.XCS(X)	; CONVERT X BITS INTO BYTES
	ADI	7
	RRC
	RRC
	RRC
	ANI	1FH
	MOV	B,A
	MOV	C,FD.YCS(X)
	MOV	L,FD.AD(X)
	MOV	H,FD.AD+1(X)
	PUSH	B
..MPY1:	PUSH	B
..MPY2:	DAD	D
	DJNZ	..MPY2
	POP	B
	DCR	C
	JRNZ	..MPY1
	PUSH	H
	MOV	A,FD.XCS(X)	; FUDGE COORDINATE TO ULHC
	CALL	COMLV
	ADD	CF.X(Y)
	MOV	E,A
	MOV	A,FD.YCS(X)
	CALL	COMUV
	ADD	CF.Y(Y)
	MOV	D,A
	CALL	R2A#
	ORI	28H	; SET XOR AND EXPAND
	OUT	MAGIC
	RES	6,H		; MAKE ADDR MAGIC
	POP	D
	POP	B
..WX1:	PUSH	B
	PUSH	H
..WX2:	LDAX	D
	INX	D
	MOV	M,A
	INX	H
	MOV	M,A
	INX	H
	DJNZ	..WX2
	MOV	M,B
	INX	H
	MOV	M,B
	POP	H
	MVI	C,BYTEPL
	DAD	B
	POP	B
	DCR	C
	JRNZ	..WX1
	RET
; DRAW THE CURSOR AT CX, CY
CURSE::	PUSH	PSW
	LDA	CURFLG#
	ANA	A
	CZ	DCURSE
	MVI	A,1
	STA	CURFLG#
	POP	PSW
	RET
; CURSOR UNWRITER
UNCURSE:: PUSH	PSW
	LDA	CURFLG#
	ANA	A
	CNZ	DCURSE
	XRA	A
	STA	CURFLG#
	POP	PSW
	RET
; CURSOR WRITER/UNWRITER
DCURSE:	PUSH	X
	PUSH	Y
	LHLD	WINPTR#
	PUSH	H
	LXI	H,VDMCR#
	SHLD	WINPTR
	LXI	Y,VDMX#
	LIXD	VDMCF#
	LDA	VDMCC#
	ANI	3	; ALWAYS XOR THE CURSOR
	CALL	CALBOX
	POP	H
	SHLD	WINPTR
	POP	Y
	POP	X
	RET
; SUBROUTINE TO LINK TO BOX COMMAND
; A= COLOR TO USE
CALBOX:
	MOV	E,CF.X(Y)
	MOV	D,CF.X+1(Y)
	MOV	L,CF.Y(Y)
	MOV	H,CF.Y+1(Y)
	PUSH	D
	PUSH	H
	MOV	E,FD.XF(X)
	MVI	D,0
	MOV	L,FD.YF(X)
	MOV	H,D
	PUSH	D
	PUSH	H
	MOV	L,A	; LOAD UP DA COLOR
	PUSH	H
	JMP	DOBOX#
; MOVE X TO THE LEFT
LEFTX:
	MOV	L,CF.X(Y)
	MOV	H,CF.X+1(Y)
	MOV	E,FD.XF(X)
	MVI	D,0
	ANA	A
	DSBC	D
	MOV	CF.X(Y),L
	MOV	CF.X+1(Y),H
	RET
; MOVE CY UP
UPY:
	MOV	L,CF.Y(Y)
	MOV	H,CF.Y+1(Y)
	MOV	E,FD.YF(X)
	MVI	D,0
	DAD	D
	MOV	CF.Y(Y),L
	MOV	CF.Y+1(Y),H
	RET
; SET CX TO LAST POSITION ON LINE
FINDLAST:
	CALL	RESCX
..MORE:	MOV	L,CF.X(Y)
	MOV	H,CF.X+1(Y)
	PUSH	H
	CALL	BUMPCX
	CALL	XCHECK
	POP	H
	JRNC	..MORE
	MOV	CF.X(Y),L
	MOV	CF.X+1(Y),H
	RET
; RESET CX AND CY TO UPPER LEFT HAND CORNER OF WINDOW
RESCXY:: 
	PUSH	X
	PUSH	Y
	LHLD	WINPTR#
	PUSH	H
	LXI	H,VDMCR#
	SHLD	WINPTR#
	LXI	Y,VDMX#
	LIXD	VDMCF#
	CALL	RESCX
	CALL	RESCY
	POP	H
	SHLD	WINPTR#
	POP	Y
	POP	X
	RET
; RESET CX TO LHS OF WINDOW
RESCX:	MOV	A,FD.XCS(X)
	DCR	A
	CALL	COMUV
	MOV	L,A
	MVI	H,0
	CALL	DEPARM
	.BYTE	WXL
	DAD	D
	MOV	CF.X(Y),L
	MOV	CF.X+1(Y),H
	RET
; SCROLL IF CY OFFSCREEN AT BOTTOM
CYSCROLL:
; IS CY ABOVE SCREEN TOP?
	CALL	CYTOPCK
	CALL	YCHECK	; IS Y OFFSCREEN AT BOTTOM
	RNC		; NO
; SET CY TO BOTTOM MOST LINE THAT IS OK MEASURED FROM TOP
	CALL	RESCY
..LOPR:	MOV	L,CF.Y(Y)
	MOV	H,CF.Y+1(Y)
	PUSH	H
	CALL	BUMPCY
	CALL	YCHECK
	POP	H
	JRNC	..LOPR
	MOV	CF.Y(Y),L
	MOV	CF.Y+1(Y),H
; BUILD CALL TO SCROLLER
	MOV	C,FD.YF(X)	; BC=SCROLL AMOUNT
	MVI	B,0
	LXI	H,0
	PUSH	H
	PUSH	H
	INR	H	; SET HL=256
	PUSH	H	; AND LET CLIPPER FIX IT
	PUSH	H
	PUSH	B
	JMP	SCROLE#
; CHECK FOR Y ABOVE UPPER LIMIT
; AND CORRECT IF NECCESSARY
CYTOPCK:
	MOV	A,FD.YCS(X)
	CALL	COMUV
	MOV	E,A
	MVI	D,0
	MOV	L,CF.Y(Y)
	MOV	H,CF.Y+1(Y)
	DAD	D
	CALL	DEPARM
	.BYTE	WYU
	CALL	CPHLDE#
; IF OFFSCREEN AT TOP RESET TO TOP OF SCREEN
	RC
; FALL TRHU IF ABOVE
; RESET CY TO SCREEN TOP
RESCY:
	CALL	DEPARM
	.BYTE	WYU
	XCHG
	MOV	A,FD.YCS(X)
	CALL	COMUV
	MOV	E,A
	MVI	D,0
	ANA	A
	DSBC	D
	MOV	CF.Y(Y),L
	MOV	CF.Y+1(Y),H
	RET
; CHECK FOR CY ONSCREEN AT BOTTOM
; CY SET IF SCROLL NEEDED
YCHECK:
	MOV	A,FD.YCS(X)
	CALL	COMLV
	MOV	E,A
	MVI	D,0FFH
	MOV	L,CF.Y(Y)
	MOV	H,CF.Y+1(Y)
	DAD	D
	CALL	DEPARM
	.BYTE	WYL
	CALL	CPHLDE#
	RET
; ROUTINE TO CHECK CX FOR BEING ONSCREEN
; RETURNS CY SET IF OFFSCREEN
XCHECK:
	MOV	L,CF.X(Y)
	MOV	H,CF.X+1(Y)
	MOV	A,FD.XCS(X)
	CALL	COMUV
	MOV	E,A
	MVI	D,0
	PUSH	H
	DAD	D
	CALL	DEPARM
	.BYTE	WXR
	XCHG		; HL=LMT, DE=EXTENT
	CALL	CPHLDE#
	POP	H
	RC
	MOV	A,FD.XCS(X)
	CALL	COMLV
	MOV	E,A
	MVI	D,0FFH
	DAD	D
	CALL	DEPARM
	.BYTE	WXL
	CALL	CPHLDE#
	RET
; ROUTINE TO BUMP CX
BUMPCX:	MOV	E,FD.XF(X)
	MVI	D,0
	MOV	L,CF.X(Y)
	MOV	H,CF.X+1(Y)
	DAD	D
	MOV	CF.X(Y),L
	MOV	CF.X+1(Y),H
	RET
; SUBTRACT YF FROM CY
BUMPCY:	MOV	E,FD.YF(X)
	MVI	D,0
	MOV	L,CF.Y(Y)
	MOV	H,CF.Y+1(Y)
	ANA	A
	DSBC	D
	MOV	CF.Y(Y),L
	MOV	CF.Y+1(Y),H
	RET
; ROUTINE TO GET WINDOW PARM INTO DE
DEPARM:
	XTHL
	MOV	E,M
	INX	H
	XTHL
	MVI	D,0
	PUSH	H
	LHLD	WINPTR#
	DAD	D
	MOV	E,M
	INX	H
	MOV	D,M
	POP	H
	RET
COMLV:
	DCR	A
	RRC
	ANI	7FH
	CMA
	INR	A
	RET
COMUV:
	RRC
	ANI	7FH
	RET
; *****
; *
; * 3 X 5 CHAR FONT
; *
; *****
FNT35:
 .BYTE 000H,000H,000H,000H,000H,040H,040H,040H,000H,040H,0A0H,0A0H
 .BYTE 000H,000H,000H,0A0H,0E0H,0A0H,0E0H,0A0H,040H,0E0H,080H,0E0H
 .BYTE 040H,080H,020H,040H,080H,020H,000H,000H,040H,0A0H,0A0H,040H
 .BYTE 040H,000H,000H,000H,040H,080H,080H,080H,040H,040H,020H,020H
 .BYTE 020H,040H,0A0H,040H,0E0H,040H,0A0H,000H,040H,0E0H,040H,000H
 .BYTE 000H,000H,000H,040H,080H,000H,000H,0E0H,000H,000H,000H,000H
 .BYTE 000H,000H,040H,000H,020H,040H,080H,000H,040H,0A0H,0A0H,0A0H
 .BYTE 040H,040H,040H,040H,040H,040H,0E0H,020H,0E0H,080H,0E0H,0E0H
 .BYTE 020H,060H,020H,0E0H,0A0H,0A0H,0E0H,020H,020H,0E0H,080H,0C0H
 .BYTE 020H,0C0H,0E0H,080H,0E0H,0A0H,0E0H,0E0H,020H,040H,040H,040H
 .BYTE 0E0H,0A0H,0E0H,0A0H,0E0H,0E0H,0A0H,0E0H,020H,0E0H,000H,040H
 .BYTE 000H,040H,000H,000H,040H,000H,040H,080H,020H,040H,080H,040H
 .BYTE 020H,000H,0E0H,000H,0E0H,000H,080H,040H,020H,040H,080H,0E0H
 .BYTE 020H,040H,000H,040H,0E0H,0A0H,0E0H,080H,0C0H,0E0H,0A0H,0E0H
 .BYTE 0A0H,0A0H,0E0H,0A0H,0C0H,0A0H,0E0H,0E0H,080H,080H,080H,0E0H
 .BYTE 0C0H,0A0H,0A0H,0A0H,0C0H,0E0H,080H,0C0H,080H,0E0H,0E0H,080H
 .BYTE 0C0H,080H,080H,0E0H,080H,0A0H,0A0H,0E0H,0A0H,0A0H,0E0H,0A0H
 .BYTE 0A0H,0E0H,040H,040H,040H,0E0H,020H,020H,020H,0A0H,0E0H,0A0H
 .BYTE 0A0H,0C0H,0A0H,0A0H,080H,080H,080H,080H,0E0H,0A0H,0E0H,0E0H
 .BYTE 0A0H,0A0H,0C0H,0A0H,0A0H,0A0H,0A0H,0E0H,0A0H,0A0H,0A0H,0E0H
 .BYTE 0E0H,0A0H,0E0H,080H,080H,0E0H,0A0H,0A0H,0E0H,020H,0C0H,0A0H
 .BYTE 0C0H,0A0H,0A0H,0E0H,080H,0E0H,020H,0E0H,0E0H,040H,040H,040H
 .BYTE 040H,0A0H,0A0H,0A0H,0A0H,0E0H,0A0H,0A0H,0A0H,0A0H,040H,0A0H
 .BYTE 0A0H,0E0H,0E0H,0A0H,0A0H,0A0H,040H,0A0H,0A0H,0A0H,0A0H,040H
 .BYTE 040H,040H,0E0H,020H,040H,080H,0E0H,0C0H,080H,080H,080H,0C0H
 .BYTE 000H,080H,040H,020H,000H,060H,020H,020H,020H,060H,040H,0E0H
 .BYTE 040H,040H,040H,020H,040H,0E0H,040H,020H
 .BYTE 040H,040H,040H,0E0H,040H
 .BYTE 080H,040H,0E0H,040H,080H
 .BYTE 000H,0A0H,040H,0A0H,000H
 .BYTE 040H,000H,0E0H,000H,040H
	.END
                                                                                                                                