	TITLE	*** COLOR COMPUTER CHARACTER GRAPHICS SOFTWARE ***
	NAME	COCOGRAPH
	WITH	WI=105,DE=51
*	EDITED 05/14/86	2000 HOURS
*	COPYRIGHT (C) 1986 BY SOFTWARE DYNAMICS
*	ALL RIGHTS RESERVED
*
VERSION	EQU	$10	LEFT DIGIT = MAJOR REV,	RIGHT DIGIT = MINOR REV
*
	IF	&*
	ORG	$2100	Base ORG Address for CoCo Char package
	FIN
*
*
CHARHEIGHT	EQU	8	# ROWS IN A CHARACTER
CHARWIDTH	EQU	6	# COLUMNS IN A CHARACTER POSITION
CHARNWIDTH	EQU	5	# COLUMNS IN A NARROW CHAR POSITION
SCREENHEIGHT	EQU	192	NUMBER OF ROWS ON THE SCREEN
SCREENWIDTH	EQU	256	NUMBER OF DOTS ACROSS THE SCREEN
CHARLEFTSIDE	EQU	1	CURSOR X AFTER NEWPAGE
CHARTOPSIDE	EQU	(SCREENHEIGHT/CHARHEIGHT)*CHARHEIGHT-1 CURSOR Y	AFTER NEWPAGE
NBROW		EQU	SCREENWIDTH/8	NUMBER OF BYTES	PER ROW
NROWS		EQU	SCREENHEIGHT	NUMBER OF ROWS DOWN SCREEN
SCREENBOTTOM	EQU	$200		16*1024-6144-512  Lowest displayable byte
		; note:	this byte is screen's upper left corner
SCREENTOP	EQU	SCREENBOTTOM+NBROW*NROWS HIGHEST ADDRESS DISPLAY BYTE
DEFAULTBACKGROUND      EQU     $FF     FOR BLACK-ON-WHITE
*	TIME DELAYS

ONESEC60HZ	EQU	60	# 60THS	SECOND IN ONE SECOND

CLICK	EQU	ONESEC60HZ/60		KEYSTROKE CLICK	TIME (NMI TICKS)
DINGTIME	EQU	ONESEC60HZ/5	"BELL" TIME FOR	CONTROL	G (NMI TICKS)
CURSORBLINK	EQU	ONESEC60HZ/2	TIME BETWEEN CURSOR BLINKS (60THS SEC)

	PAGE
*	SPECIAL	KEYSTROKES
*
CTRLD	EQU	$04	CONTROL	D (ACTIVATE DEBUG)
LF	EQU	$0A	LINE FEED
CR	EQU	$0D	CARRIAGE RETURN
	PAGE
*	PICTURE	BLOCK DISPLACEMENTS
*
PICTXSIZ	EQU	0		X SIZE OF PICTURE IN BITS
PICTYSIZ	EQU	PICTXSIZ+2	Y SIZE OF PICTURE IN ROWS
PICTBYT		EQU	PICTYSIZ+2	1ST BYTE OF PICTURE DATA

	PAGE	GRAPHBOX CONTROL VARIABLES
	 with  wi=132,de=66
XORIGIN	RMB	2	X POSITION OF LOWER LEFT CORNER	IN VIRTUAL DISPLAY
YORIGIN	RMB	2	Y POSITION OF LOWER LEFT CORNER	IN VIRTUAL DISPLAY
XWINDOWTOP	RMB	2	X TOP OF WINDOW	IN VIRTUAL DISPLAY
YWINDOWTOP	RMB	2	Y TOP OF WINDOW	IN VIRTUAL DISPLAY
******** THE ABOVE 4 AREN'T USEFUL YET..********
CURSORBYTE	RMB 2	POINTER	TO SCREEN BYTE CONTAINING CURSORBIT
CURSORBIT	RMB 2	BIT NUMBER OF SCREEN BYTE SELECTED BY (CURSORX,	CURSORY)
WRITEATOSCREEN	FDB SELECTEORMODE+2	Pointer	to SUBROUTINE TO WRITE (A) TO (U)
*				(EORMODE, IORMODE OR ANDMODE)
NARROWCHAR	FCB 0	42/54 char per line, Default to 42 char/line
CHARSHIFTBIAS	RMB 1	SHIFT BIAS FOR NORMAL VS. NARROW CHAR TABLE
CHARSETTABLE	RMB 2	ADDRESS OF NORMAL/NARROW CHARACTER TABLES
CHARLINEWIDTH	RMB 1	OFF END OF LINE VALUE
NEWX		RMB 2	NEW VALUE OF CURSORX
SHIFT		RMB 2	POINTER	TO ROUTINE TO SHIFT DATA PATTERN
ROWCOUNT	RMB 1	NUMBER OF ROWS OF CHARACTER LEFT TO COPY TO SCREEN
TARGETLEFT	RMB 2	PLACE ON SCREEN	TO PUT LEFT BYTE OF NEXT ROW OF	CHARACTER
TARGETRIGHT	RMB 2	PLACE ON SCREEN	TO PLACE RIGHTMOST CHARACTER ???
DELTAXSIGN	RMB 1	SIGN OF	DELTA X	(0 OR :FF)
DELTAYSIGN	RMB 1	SIGN OF	DELTA Y	(0 OR :FF)
*	NOTE! DELTAX, DELTAY MUST BE IN	THIS EXACT ORDER FOR "RASSOCIATE"
DELTAX		RMB 2	DIFFERENCE BETWEEN CURSOR AND TARGETX
DELTAY		RMB 2	DIFFERENCE BETWEEN CURSORY AND TARGETY
TARGETX	RMB 2	LOGICAL	X POSITION TARGET
TARGETY	RMB 2	LOGICAL	Y POSITION TARGET

PICTUREP	RMB 2	POINTER	TO ASSOCIATION TABLE ENTRY
PICTURE	RMB	2	POINTER	TO PICTURE BLOCK
PICTOP	RMB	2	POINTER	TO TOP OF PICTURE BLOCK	REGION

MULTIPLIER	RMB 1	USED TO	COMPUTE	# BYTES	IN A PICTURE
PWIDTH		RMB 1	WIDTH OF PICTURE (ROUNDED UP) IN BYTES
WIDTHCNT	RMB 1	DOWN COUNTER USED TO SCAN PICTURE ROW
RESIDUE		RMB 1	PARTIAL	PICTURE	BYTE NOT YET PLACED ON SCREEN

LEFTEND		RMB 1	LEFT END OF TOP	(BOTTOM) LINE OF A BOX
LEFTCOLUMN	RMB 1	LEFT EDGE OF (SIDE OF) EMPTY BOX
RIGHTEND	RMB 1	RIGHT END OF TOP (BOTTOM) LINE OF A BOX
RIGHTCOLUMN	RMB 1	RIGHT EDGE OF (SIDE OF)	BOX
CURSORON	RMB 1	REMEMBERS THAT CURSOR IS DISPLAYED
CURSORBLINKDELAY RMB 2	counts down to toggle cursor blink
	 page
	*	CONTROL	FUNCTION ENTRY POINTS

CONTROLCHARBRANCH
	FDB	RETURN		$00 NULL (ILLEGAL)
	FDB	SETCHCURSOR	$01 CONTROL A; (A) = ROW, (B)= COL
	FDB	RETURN		$02 CONTROL B
	FDB	RETURN		$03 CONTROL C
	FDB	RETURN		$04 CONTROL D
	FDB	ERASETOEOL	$05 CONTROL E
	FDB	RETURN		$06 CONTROL F
	FDB	DING		$07 CONTROL G
	FDB	BACKSPACE	$08 CONTROL H
	FDB	RETURN		$09 CONTROL I
	FDB	CHCURSORDOWN	$0A CONTROL J
	FDB	RETURN		$0B CONTROL K
	FDB	NEWPAGE		$0C CONTROL L
	FDB	ENDLINE		$0D CONTROL M
	FDB	RETURN		$0E CONTROL N
	FDB	RETURN		$0F CONTROL O
	FDB	RETURN		$10 CONTROL P
	FDB	RETURN		$11 CONTROL Q
	FDB	CHCURSORRIGHT	$12 CONTROL R
	FDB	CHCURSORLEFT	$13 CONTROL S
	FDB	RETURN		$14 CONTROL T
	FDB	RETURN		$15 CONTROL U
	FDB	RETURN		$16 CONTROL V
	FDB	RETURN		$17 CONTROL W
	FDB	RETURN		$18 CONTROL X
	FDB	RETURN		$19 CONTROL Y
	FDB	RETURN		$1A CONTROL Z
	FDB	RETURN		$1B CONTROL [ (GRAPHICS	COMMAND	PREAMBLE)
	FDB	RETURN		$1C CONTROL BACKSLASH
	FDB	RETURN		$1D CONTROL ]
	FDB	CHCURSORUP	$1E CONTROL UP ARROW
	FDB	RETURN		$1F CONTROL LEFT ARROW
	 org   (*//$100)*$100	       org to next convenient page (debug only)

	PAGE	DRAW ASSOCIATED, DRAW PICTURE

DRAWPICTURE ; (X) points to picture block, put picture on screen
	LDD	PICTYSIZ,X	FETCH PICTURE SIZE
	LDX	PICTXSIZ,X
	BEQ	PICTXIT		EXIT IF	PICTURE	IS 0 BYTES WIDE
	leau	pictbyt,x	form pointer to	1st byte of picture bit	image
DrawPictureSizeXDatU ; draw picture whose bits are at (U), size	is in (X,D)
	stu	picture		save pointer to	picture
	JSR	MAKESPACE	MAKE SURE ENOUGH SPACE EXISTS
				; and roll screen up enough if it doesn't
	JSR	GENCURSORBYTE	FIGURE OUT WHERE FIRST BYTE GOES
	STX	TARGETLEFT
	LDX	NEWX		UPDATE CURSORX PAST THE	PICTURE
	STX	CURSORX
SPLAT1 ; entry point for drawing characters, crosshairs	and cursor
; (B) =	lower 3	bits of	X coordinate
; PICTURE points to raw	bit image to display
	ASLB			DOUBLE BIT INDEX FOR WORD TABLE	BRANCH
	ldx	#DRAWSHF	find draw shift	routine, which shifts each
	ldy	b,x		picture	byte before placing it on screen
	LDD	DELTAX		COMPUTE	PICTURE	WIDTH IN BYTES
	ADDD	#7		ROUND WIDTH IN DOTS TO BYTES
	LSRD			# DOTS + 7 <= 512 + 7 =	519 MAX
	LSRD
	LSRB
	BEQ	PICTXIT		QUIT IF	PICTURE	IS ZERO	BYTES WIDE
	STAB	PWIDTH		SAVE PICTURE WIDTH
	LDX	PICTURE		FETCH PICTURE BYTE TO PLACE ON SCREEN
	LDU	CURSORBYTE	PLACE ON SCREEN	TO PUT THE BYTE
PICTLINE	EQU	*	DRAW REMOTE PICTURE LINE ON SCREEN
	LDAB	PWIDTH		GET NUMBER OF BYTES PER	PICTURE	ROW
	STAB	WIDTHCNT	USE AS LOOP LIMIT COUNT
	CLR	RESIDUE		ZERO THE RESIDUE BYTE
PICTBYTE ; DRAW	REMOTE PICTURE BYTE ON SCREEN
; (X) points to	next picture byte to draw
;     (note: rightmost picture bit is bit 0 of some byte)
; (U) points to	next screen byte to update (CURSORBYTE)
; (Y) points to	picture	shift routine
	LDAA	,X+		BUMP POINTER TO	PICTURE	BLOCK
	CLRB			NEED 8 ZERO BITS TO SHIFT INTO
	JMP	,y		GO SHIFT BYTE; THEN COPY TO SCREEN

PICTXIT	EQU     *
	RTS

PRSHIFT3 LSRD			SHIFT RIGHT 3
PRSHIFT2 LSRD			SHIFT RIGHT 2
PRSHIFT1 LSRD			SHIFT RIGHT 1
PRSHIFT0 ;			SHIFT RIGHT 0
	ORAA	RESIDUE		COMBINE	SHIFTED	STUFF WITH RESIDUE FROM	LAST TIME
	STAB	RESIDUE		WHAT'S LEFT OVER IS RESIDUE FOR	NEXT TIME
	JSR	[WRITEATOSCREEN] COPY PICTURE BYTE TO SCREEN
	DEC	WIDTHCNT	MORE BYTES IN THIS PICTURE ROW ?
	BNE	PICTBYTE	YES, GO	COPY TO	SCREEN
	BRA	PICTNEXTROW	FIGURE OUT WHERE NEXT BYTE SHOULD GO

PLSHIFT4 ASLA			LEFT SHIFT 4 PLACES
	 ROLB			NOTE: ASLA\ROLB	is NOT same as ASLD!!!
PLSHIFT3 ASLA			LEFT SHIFT 3 PLACES
	 ROLB
PLSHIFT2 ASLA			LEFT SHIFT 2 PLACES
	 ROLB
PLSHIFT1 ASLA			LEFT SHIFT 1 PLACE
	 ROLB
	ORAB	RESIDUE		COMBINE	WITH RESIDUE FROM BYTE TO LEFT
	STAA	RESIDUE		WHAT'S LEFT OVER IS RESIDUE FOR	NEXT TIME
	TFR	B,A		COPY BYTE TO (A)
	JSR	[WRITEATOSCREEN] KICK PICTURE BYTE TO SCREEN
	DEC	WIDTHCNT	MORE BYTES IN THIS PICTURE ROW ?
	BNE	PICTBYTE	YES, GO	COPY TO	SCREEN
PICTNEXTROW ; COMPUTE SCREEN ADDRESS OF	NEXT PICTURE BYTE ROW
	LDAA	RESIDUE		BY COPYING RESIDUE TO SCREEN
	JSR	[WRITEATOSCREEN]
	DEC	DELTAY+1	MORE PICTURE ROWS TO SHOW ?
	BEQ	PICTXIT		NO, I GIVE UP
	LDB	#NBROW-1	MOVE DOWN THE SCREEN ONE ROW (-1 for RESIDUE)
	SUBB	PWIDTH		delta =	bytes per row minus bytes displayed
	LEAU	B,U		U now points to	next row leftmost picture byte
	; assert: we cannot run	off "top" of screen!
	BRA	PICTLINE	GO DRAW	NEXT PICTURE LINE

DRAWSHF	EQU	*	REMOTE PICTURE BYTE SHIFT TABLE
	PRSHIFT0		BIT 0
	PRSHIFT1		BIT 1
	PRSHIFT2		BIT 2
	PRSHIFT3		BIT 3
	PLSHIFT4		BIT 4
	PLSHIFT3		BIT 5
	PLSHIFT2		BIT 6
	PLSHIFT1		BIT 7

	PAGE	DISPLAY	PRINTING CHARACTER
	page
CHARACTERSET	EQU	*	ASCII TO BIT PATTERN CONVERSION	TABLE
	 list  0		       just uses up paper
	INCLUDE	RSSDCHARSET.ASM
	 list 1
	page
NCHARACTERSET	EQU	*	ASCII TO BIT PATTERN CONVERSION	TABLE (NARROW)
	 list  0		       just uses up paper
	INCLUDE	RSSDNCHARSET.ASM
	 list 1
	 page
	PAGE	GRAPHICS TERMINAL EMULATION

PUTCHAR	; (A) contains 7 bit ASCII code
	LDB	NARROWCHAR	NARROW CHARACTER?
	BEQ	NORMALCHAR	B/NO
	LDB	#(SCREENWIDTH-CHARNWIDTH-1)
	STB	CHARLINEWIDTH	SET LINE WIDTH
	CLRB
	STB	CHARSHIFTBIAS	SET SHIFT BIAS FOR NARROW
	LDX	#NCHARACTERSET
	STX	CHARSETTABLE	SET CHARACTER TABLE
	BRA	PUTCHARMASK

NORMALCHAR
	LDB	#(SCREENWIDTH-CHARWIDTH-1)
	STB	CHARLINEWIDTH	SET LINE WITH TO NORMAL
	LDB	#1
	STB	CHARSHIFTBIAS	SET SHIFT BIAS FOR NORMAL
	LDX	#CHARACTERSET
	STX	CHARSETTABLE	SET CHARACTER TABLE

PUTCHARMASK
	CMPA	#$1F		A CONTROL CHARACTER ?
	BHI	DISPLAYCHAR	B/ PRINTING CHARACTER, GO PRINT
	ASLA			IT'S A CONTROL CHARACTER !
	ldx	#ControlCharBranch
	jmp	[a,x]		call processing	subroutine

DING ; output <BEL> sound
RETURN	RTS			YOU GUESS...

DISPLAYCHAR ; DISPLAY PRINTING CHARACTER (A)
	PSHA			SAVE THE CHARACTER, WE NEED IT LATER
	LDX	CURSORX		IS THIS	LINE FULL ?
	CMPX	#(SCREENWIDTH-CHARWIDTH-1) ... ?
	BLS	CHAR1		NO, GO CHECK FOR OVERRUN BOTTOM	OF SCREEN
	LDX	#CHARLEFTSIDE	CHARACTER WOULD	RUN OFF	RIGHT SIDE OF SCREEN
	STX	CURSORX		SO PUT CURSOR BACK TO LEFT SIDE	OF SCREEN
	LDD	CURSORY		NOW MOVE DOWN THE SCREEN A ROW
	SUBD	#CHARHEIGHT	RUN OFF	BOTTOM OF SCREEN ?
	BLO	CHAR2		YES, MUST ROLL SCREEN
	STD	CURSORY		(ADVANCE CURSORY DOWN A	CHARACTER ROW)
CHAR1	EQU	*	CHECK FOR OVERRUN BOTTOM OF SCREEN
	LDD	CURSORY		GET VERTICAL CURSOR POSITION
	CMPD	#CHARHEIGHT-1	DOES NEXT LINE RUN OFF BOTTOM OF SCREEN ?
	BHS	CHARPUTC	NO, JUST GO DISPLAY THE	CHARACTER
CHAR2	EQU	*		MUST ROLL SCREEN MORE THAN 1 CHARACTER LINE
	SUBD	#CHARHEIGHT-1+(SCREENHEIGHT-(SCREENHEIGHT/CHARHEIGHT)*CHARHEIGHT)
*				ADD ANOTHER LINE TO OVERRUN DISTANCE
CHARR	EQU	*		ROLL THE SCREEN; (D) = - # LINES
	JSR	ROLLUPCHARLINE	ROLL THE SCREEN	UP ONE CHARACTER LINE
*	NEXT, WE OUTPUT	THE CHARACTER TO THE SCREEN
CHARPUTC ; NOW PUT CHARACTER ON	THE SCREEN
	PULA			GIMME MY CHARACTER BACK !
	SUBA	#$20		subtract of bias for control characters
	BEQ	CHARPUTX	b/ blank, clean	up and exit
	LDB	#7		MULTIPLY CHARACTER BY 7
	MUL
	LDX	#CHARACTERSET-7	COMPUTE	POINTER	TO DOT MATRIX PATTERN
	LEAX	D,X
	STX	PICTURE		AND SAVE IT
	LDD	CURSORY		IF WE ARE DISPLAYING A LETTER WITH A TAIL,
	TST	0,X		THEN PLACE ON SCREEN 1 LINES BELOW NORMAL
	BPL	CPUT1		B/ NO TAIL (not	small G,J,P,Q,Y)
	SUBD	#1		TAIL, SKIP DOWN	SCREEN ONE LINE
CPUT1	JSR	GENCURSORCHAR	GET POINTER TO BYTE WHICH CURSOR SELECTS
	STX	TARGETLEFT	SAVE POINTER TO	LEFT TARGET BYTE
	ADDB	CHARSHIFTBIAS	BIAS SHIFT FOR NORMAL/NARROW
	ASLB			DOUBLE BIT INDEX FOR WORD JUMP TABLE
	LDX	#CSHIFTBL	compute	pointer	to shift routine
	LDY	B,X
	LDAA	#CHARHEIGHT-1		GET NUMBER OF ROWS TO INSERT
	STAA	ROWCOUNT	SET UP LOOP LIMIT COUNTER
*
*	THE PUMP IS PRIMED, NOW	LET'S INSERT THE CHARACTER DOT MATRIX
*
	LDX	PICTURE		GET POINTER TO CHARACTER ROW
	LDU	TARGETLEFT	GET POINTER TO LEFT HALF OF TARGET
	LDA	,X+		FETCH 1ST ROW OF DOT MATRIX TO INSERT
	ANDA	#$1F		MASK OFF "TAIL"	FLAG
	CLRB			IN CASE	WE MUST	SHIFT RIGHT
	JMP	0,Y		GO SHIFT AND INSERT ROW

CHARPUTX ; DONE	INSERTING CHARACTER ON SCREEN
	LDD	CURSORX		GRAB CURSOR POINTER
	ADDD	#CHARWIDTH	ADVANCE	IT TO NEXT CHARACTER POSITION
	; (THIS	CANNOT OVERRUN THE RIGHT EDGE OF THE SCREEN)
	STD	CURSORX
	RTS			RETURN TO CALLER

CSHIFTL4 ASLA			SHIFT DOT MATRIX LEFT 4	BITS
CSHIFTL3 ASLA			SHIFT DOT MATRIX LEFT 3	BITS
CSHIFTL2 ASLA			SHIFT DOT MATRIX LEFT 2	BITS
CSHIFTL1 ASLA			SHIFT DOT MATRIX LEFT 1	BIT
CSHIFT0	 JSR	[WRITEATOSCREEN] STORE BIT PATTERN FOR CHARACTER TO SCREEN
	DEC	ROWCOUNT	ANY MORE ROWS LEFT TO INSERT ?
	BEQ	CHARPUTX	NO, JUST ADVANCE THE CURSOR
	LEAU	NBROW-1,U	ADVANCE	POINTER	TO NEXT	ROW
	LDA	,X+		FETCH NEXT ROW OF DOT MATRIX
*	CLRB			IF WE GET HERE,	WE'LL NEVER SHIFT RIGHT!
	JMP	,Y		GO SHIFT AND INSERT CHARACTER ROW

CSHIFTR4 LSRA			SHIFT RIGHT 4 PLACES
	 RORB
CSHIFTR3 LSRA			SHIFT RIGHT 3 PLACES
	 RORB
CSHIFTR2 LSRA			SHIFT RIGHT 2 PLACES
	 RORB
CSHIFTR1 LSRA			SHIFT RIGHT 1 PLACE
	 RORB
	JSR	[WRITEATOSCREEN]
	TFR	B,A		COPY RIGHT HALF	OF CHARACTER TO	(A)
	JSR	[WRITEATOSCREEN] INSERT	RIGHT HALF OF CHARACTER
	DEC	ROWCOUNT	ANY MORE ROWS LEFT TO INSERT ?
	BEQ	CHARPUTX	NO, JUST ADVANCE THE CURSOR
	LEAU	NBROW-2,U	ADVANCE	POINTER	TO NEXT	ROW
	LDA	,X+		FETCH NEXT ROW OF DOT MATRIX
	CLRB			IN CASE	WE MUST	SHIFT RIGHT
	JMP	,Y		GO SHIFT AND INSERT CHARACTER ROW

CSHIFTBL ; POINTERS TO CHARACTER SHIFT ROUTINES
	CSHIFTL4		BIT # =0 --> SHIFT LEFT 4
	CSHIFTL3		BIT # =0 --> SHIFT LEFT 3
	CSHIFTL2		=1 --> LEFT 2
	CSHIFTL1		ETC.
	CSHIFT0
	CSHIFTR1
	CSHIFTR2
	CSHIFTR3
	CSHIFTR4
	 org   (*//$100)*$100	       org to next convenient page (debug only)
	PAGE	GRAPHICS TERMINAL EMULATION

	 org   (*//$100)*$100	       org to next convenient page (debug only)
	 page
SETCURSORX	EQU	*	SETS X VALUE OF	CURSOR TO (X)
	STX	CURSORX
	RTS

SETCURSORY	EQU	*	SETS Y VALUE OF	CURSOR TO (D)
	STD	CURSORY		STORE AS CURSORY Y VALUE
	RTS			AND EXIT

SETCURSORXY	EQU	*	SET CURSOR X TO	(X), CURSORY TO	(A)
	STX	CURSORX
	STD	CURSORY
	RTS
	PAGE
*
DRAWDOTATXY ; SET CURSOR X,Y AND DRAW DOT
	BSR	SETCURSORXY
*	DRAWDOT	 --  SUBROUTINE	TO DRAW	DOT AT (CURSORX, CURSORY)
*
DRAWDOT	EQU     *
	JSR	GENCURSORBYTE	GET BIT	NUMBER
	LDX	#BITMSK		CONVERT	BIT NUMBER TO BIT MASK
	LDA	B,X
	LDU	CURSORBYTE	GO UPDATE THE SELECTED BYTE
	JMP	[WRITEATOSCREEN] MODIFY	THE DISPLAY MEMORY
*	RTS

BITMSK	FCB	%10000000	BIT # 0
	FCB	%01000000	BIT # 1
	FCB	%00100000	BIT # 2
	FCB	%00010000	BIT # 3
	FCB	%00001000	BIT # 4
	FCB	%00000100	BIT # 5
	FCB	%00000010	BIT # 6
	FCB	%00000001	BIT # 7
       PAGE    DRAW DOT	AND MOVE CURSOR	ROUTINES
DOTAMCU	; DRAW DOT AND MOVE CURSOR UP
	BSR	DRAWDOT
MOVECU ; MOVE CURSOR UP
	BRA	BUMPCURSORY	MOVE CURSOR UP

DOTAMCUR ; DRAW	DOT AND	MOVE CURSOR UP AND RIGHT
	BSR	DRAWDOT
MOVECUR	; MOVE CURSOR UP AND RIGHT
	BSR	BUMPCURSORY
	BRA	BUMPCURSORX

DOTAMCR	; DRAW DOT AND MOVE CURSOR RIGHT
	BSR	DRAWDOT
MOVECR ; MOVE CURSOR RIGHT
	BRA	BUMPCURSORX

DOTAMCRD ; DRAW	DOT AND	MOVE CURSOR RIGHT AND DOWN
	BSR	DRAWDOT
MOVECRD	; MOVE CURSOR RIGHT AND	DOWN
	BSR	BUMPCURSORX
	JMP	DECCURSORY

DOTAMCD	; DRAW DOT AND MOVE CURSOR DOWN
	BSR	DRAWDOT
MOVECD ; MOVE CURSOR DOWN
	JMP	DECCURSORY

DOTAMCDL ; DRAW	DOT AND	MOVE CURSOR DOWN AND LEFT
	BSR	DRAWDOT
MOVECDL	; MOVE CURSOR DOWN AND LEFT
	BSR	DECCURSORY
	JMP	DECCURSORX

DOTAMCL	; DRAW DOT AND MOVE CURSOR LEFT
	BSR	DRAWDOT
MOVECL ; MOVE CURSOR LEFT
	JMP	DECCURSORX

DOTAMCLU ; DRAW	DOT AND	MOVE CURSOR LEFT AND UP
	BSR	DRAWDOT
MOVECLU	; MOVE CURSOR LEFT AND UP
	BSR	DECCURSORX
	BRA	BUMPCURSORY
*      BUMPCURSORX -- BUMPS CURSORX OR LEFT ROTATES THE	SCREEN
*
BUMPCURSORX	EQU     *
	LDX	CURSORX		DO WHAT	WE SAID !
*	CPX	#SCREENWIDTH-1	AT RIGHT EDGE OF SCREEN ?
*	BEQ	ROLLSCREENLEFT	(B/ YES)
	INX			NO, SO BUMP THE	CURSORX
	STX	CURSORX		SAVE UPDATED VALUE
	RTS			AND EXIT

*	DECCURSORX -- DECREMENT	CURSORX	OR RIGHT ROTATE	THE SCREEN
*
DECCURSORX	EQU     *
	LDX	CURSORX		DO WHAT	HE SAID
	BEQ	ROLLSCREENRIGHT	AT LEFT	EDGE OF	SCREEN ?
	DEX			NO, SO DECREMENT THE CURSORX
	STX	CURSORX		STORE THE UPDATED VALUE
ROLLSCREENRIGHT	;NO SCREEN SHIFTING YET
	RTS			AND EXIT
	 page
*      BUMPCURSORY -- BUMPS CURSORY OR ROLLS SCREEN DOWN
*
BUMPCURSORY	EQU     *
	INC	CURSORY		DO IT
	BNE	BUMPRTS		EXIT IF	ITS OK
	DEC	CURSORY		RAN OFF	TOP OF SCREEN
	JMP	ROLLSCREENDOWN
*
*	DECCURSORY -- DECREMENTS CURSORY OR ROLLS SCREEN UP
*
DECCURSORY	EQU     *
	LDD	CURSORY		ARE WE AT BOTTOM OF SCREEN ?
	BNE	DECCURSORY1	NO, WE CAN DO IT!
ROLLSCREENUP	EQU     *
	LDD	#1		DISTANCE TO ROLL SCREEN	UP
	JMP	MODIFYSCREENSHIFT

DECCURSORY1	EQU     *
	SUBD	#1		DO WHAT	WE PROMISED
	STAA	CURSORY
BUMPRTS	RTS			AND GET	OUT...
	 page
ROLLSCREENDOWN	EQU     *
	 LDD   #-1		DISTANCE TO ROLL SCREEN	UP, IN LINES
MODIFYSCREENSHIFT ; (D)	contains # scan	lines to roll screen up
;  shuffles from high part of display area to lower addresses
	if      0
	tsta
	bmi	modifyscreenshift1 b/ must roll	screen down
	fin
	ldu	#ScreenBottom-NBRow+16 = shuffle to target
	lda	#nbrow		figure out distance to move screen lines
	mul
	leax	d,u		= shuffle from source
MODIFYSCREENSHIFTSHUFFLEUP
	ldd	-16,x
	std	-16,u
	ldd	-14,x
	std	-14,u
	ldd	-12,x
	std	-12,u
	ldd	-10,x
	std	-10,u
	ldd	-8,x
	std	-8,u
	ldd	-6,x
	std	-6,u
	ldd	-4,x
	std	-4,u
	ldd	-2,x
	std	-2,u
	ldd	,x
	std	,u
	ldd	2,x
	std	2,u
	ldd	4,x
	std	4,u
	ldd	6,x
	std	6,u
	ldd	8,x
	std	8,u
	ldd	10,x
	std	10,u
	ldd	12,x
	std	12,u
	ldd	14,x
	std	14,u
	leax	32,x
	leau	32,u
; assert: number of bytes per row is divisible by 8
	cmpx	#ScreenTop+16 shuffle complete ?
	bne	modifyscreenshiftshuffleup
	rts

	if      0
modifyscreenshift1
	ldu	#ScreenTop-NBRow+16 = shuffle to target
	lda	#nbrow		figure out distance to move screen lines
	mul
	negd
	leax	d,u		= shuffle from source
MODIFYSCREENSHIFTSHUFFLEDOWN
	ldd	-16,x
	std	-16,u
	ldd	-14,x
	std	-14,u
	ldd	-12,x
	std	-12,u
	ldd	-10,x
	std	-10,u
	ldd	-8,x
	std	-8,u
	ldd	-6,x
	std	-6,u
	ldd	-4,x
	std	-4,u
	ldd	-2,x
	std	-2,u
	ldd	,x
	std	,u
	ldd	2,x
	std	2,u
	ldd	4,x
	std	4,u
	ldd	6,x
	std	6,u
	ldd	8,x
	std	8,u
	ldd	10,x
	std	10,u
	ldd	12,x
	std	12,u
	ldd	14,x
	std	14,u
	leax	-32,x
	leau	-32,u
; assert: number of bytes per row is divisible by 8
	cmpx	#ScreenBottom-16 shuffle complete ?
	bne	modifyscreenshiftshuffledown
	rts
	fin
	 page
*	GENCURSORBYTE -- RETURNS POINTER TO BYTE ON SCREEN IN (X)
*	WHICH CONTAINS THE BIT SPECIFIED BY CURSORX, CURSORY
*	ALSO SETS CURSORBYTE TO	(X)
*	(B) = BIT NUMBER  (0 = MSB, 7 =	LSB)
*	BYTE = CURSORY*ROWSIZE+INT(CURSORX/8)
*	BIT = CURSORX MOD 8
*
*	GENCURSOR1 IS ENTRY POINT WITH (A,B) = X POSITION
*		AND TOP	OF STACK = Y POSITION
*
; on color computer, x and y are limited to 255!!!
GENCURSORBYTE	EQU     *
	LDD	CURSORY		GET Y POSITION
GENCURSORCHAR ;	ENTRY TO GENERATE CURSORBYTE FOR CHARACTER DISPLAY
	NEGD			OFFSET INTO BUFFER
	ADDD	#SCREENHEIGHT-1	produces 0 for max Y position
	LDX	#SCREENBOTTOM	= (X,Y)	= (0,255)
	LDA	#NBROW
	MUL
	PSHD			(D) = offset to	desired	screen row
	LDD	CURSORX
	LSRD			compute	cursorx	divided	by 8
	lsrb			...=/4;	assert:	(A)=0
	lsrb			...=/8
	addd	,s++		combine	with row offset
	leax	d,x		pointer	to desired location
	STX	CURSORBYTE	SAVE POINTER WHERE WE PROMISED
	LDB	CURSORX+1	GET BIT	NUMBER BACK
	ANDB	#7		= CURSORX MOD 8
	RTS			AND EXIT

GENCURSOR1 ; ENTRY POINT FOR "SPLAT2"
; this routine is wrong!
;	(A) = Y	position
;	(B) = X	position
	LDX	#SCREENBOTTOM	= (0,0)
	LDB	#NBROW
	MUL
	PSHD			(D) = offset to	desired	screen row
	LDD	CURSORX
	LSRD			compute	cursorx	divided	by 8
	lsrb			...=/4;	assert:	(A)=0
	lsrb			...=/8
	addd	,s++		combine	with row offset
	leax	d,x		pointer	to desired location
	STX	CURSORBYTE	SAVE POINTER WHERE WE PROMISED
	LDB	CURSORX		GET BIT	NUMBER BACK
	ANDB	#7		= CURSORX MOD 8
	RTS			AND EXIT
	page
	 org   (*//$100)*$100	       org to next convenient page (debug only)
*	CLEARLINES -- SUBROUTINE TO CLEAR HORIZONTAL SCREEN LINES
*	(X) POINTS TO 1ST BYTE OF LINE
*	(B) CONTAINS LINE COUNT
*	CLEARS LINES ABOVE AND INCLUDING (X) ON	SCREEN
*
CLEARLINES	EQU     *
	LEAX	16,X		to compensate for STD -16,X below
	STB	TEMPB
	LDA	CURRENTBACKGROUND GET BACKGROUND TO STORE
	TFR	A,B
CLEARLOOP	EQU     *
	RPT	16
	STD	*-CLEARLOOP-16,X clear 32 bytes	(1 screen row)
	LEAX	32,X		advance	(X) to "start" of next row
	DEC	TEMPB		ALL ROWS ZEROED ?
	BNE	CLEARLOOP	B/ no, go clear	another!
CLEARRTS
	RTS

NEWPAGE	EQU     *
	LDX	#SCREENBOTTOM	ZERO THE ENTIRE	SCREEN
	LDD	#SCREENHEIGHT
	JSR	CLEARLINES
	LDX	#CHARLEFTSIDE	POSITION CURSOR...
	STX	CURSORX		AT TOP LEFT CORNER OF SCREEN
	LDX	#CHARTOPSIDE
	STX	CURSORY
	RTS			ALL DONE !

SETCHCURSOR ; (A)= ROW,	(B)= COLUMN; (0,0) is upper left corner
	PSHB			save column number
	LDAB	#CHARHEIGHT	Scan lines/character row
	MUL			= Scan lines to	skip (assert: <	256!)
	NEGD			ROW #0 = MAX Y POSITION
	ADDD	#CHARTOPSIDE
	STD	CURSORY
	PULB			get character column number
	LDAA	#CHARWIDTH	convert	to X dot number
	MUL
	ADDD	#CHARLEFTSIDE	add position of	leftmost character column
	STD	CURSORX		RESULT <= 511 GAURANTEED!!
	RTS
	PAGE
BACKSPACE	EQU	*	BACKSPACE THE CHARACTER	CURSOR AND ERASE
	LDD	CURSORX		GET CURRENT CURSOR POSITION
	SUBD	#CHARWIDTH	BACK UP	ONE CHARACTER WIDTH
	BCC	BACKSPACE1	B/ DIDN'T RUN OFF LEFT SIDE OF SCREEN
	LDD	#CHARLEFTSIDE	DID RUN	OFF LEFT SIDE, STOP IT AT LEFT SIDE
BACKSPACE1	EQU     *
	STD	CURSORX		UPDATE CURSOR POSITION
	LDX	#CHARWIDTH	NOW STOMP ON THE CHARACTER
	LDD	#CHARHEIGHT
	JSR	BLANKREGION
CHCURSORLEFT	EQU	*	MOVE CHARACTER CURSOR LEFT
	LDD	CURSORX		GET CURRENT CURSOR POSITION
	SUBD	#CHARWIDTH	MOVE IT	LEFT 6 DOT POSITIONS
	BCS	ENDLINE		GO IF RUNS OFF LEFT SIDE OF SCREEN
CHCURSORXSTAB	EQU	*	STORE (A,B) INTO CURSORX
	STD	CURSORX
	RTS

CHCURSORRIGHT	EQU	*	MOVE CURSOR ON CHARACTER POSITION TO THE RIGHT
	LDD	CURSORX		GET THE	CURRENT	CURSOR
	ADDD	#CHARWIDTH	ADVANCE	TO RIGHT 6 COLUMNS
	CMPD	#(SCREENWIDTH/CHARWIDTH*CHARWIDTH-CHARWIDTH)/256
	BLS	CHCURSORXSTAB	GO IF UPDATED VALUE IS OK
CHCURSORXMAX	EQU	*	NEW VALUE FOR CURSOR IS	PAST RIGHT SIDE	OF SCRREN
	LDX	#(SCREENWIDTH/CHARWIDTH)*CHARWIDTH-CHARWIDTH-1
	STX	CURSORX		FORCE TO RIGHTMOST SCREEN CHARACTER POSITION
	RTS			AND QUIT

ENDLINE	EQU	*	END OF LINE SEEN ($0D)
	LDX	#CHARLEFTSIDE	MOVE CURSOR TO LEFT SIDE OF SCREEN
	STX	CURSORX		WITHOUT	MOVING DOWN A ROW
	RTS			GO PROCESS THE NEXT COMMAND
	PAGE
CHCURSORUP	EQU	*	MOVE CURSOR UP ONE CHARACTER ROW
	LDD	CURSORY		GET CURRENT ROW	POSITION
	ADDD	#CHARHEIGHT	BUMP IT	BY ONE CHARACTER ROW
	CMPD	#SCREENHEIGHT-1	OFF TOP	OF SCREEN ?
	BLS	CHCURSORYSTAB	GO STORE THE VALUE IF NOT OFF TOP OF SCREEN
	LDD	#SCREENHEIGHT-1	OFF TOP	OF SCREEN, MOVE	BACK
CHCURSORYSTAB	EQU	*	STORE (A) INTO CURSORY
	STD	CURSORY		DO IT !
	RTS

CHCURSORDOWN	EQU	*	MOVE CURSOR DOWN ONE CHARACTER ROW
	LDD	CURSORY		GET CURRENT ROW	POSITION
	SUBD	#CHARHEIGHT	MOVE DOWN SCREEN ONE CHARACTER ROW
	BCS	CHCURSORYMIN	OOPS, RAN OFF BOTTOM OF	SCREEN
	CMPD	#CHARHEIGHT-1	NOT QUITE, STILL A CHARACTER ROW LEFT ?
	BCC	CHCURSORYSTAB	YES, GO	STORE VALUE
CHCURSORYMIN	EQU	*	RAN OFF	BOTTOM OF SCREEN, ROLL SCREEN
	SUBD	#CHARHEIGHT-1+(SCREENHEIGHT-(SCREENHEIGHT/CHARHEIGHT)*CHARHEIGHT)
*				COMPUTE	MINUS NUMBER OF	LINES TO CLEAR
*
*	ROLLUPCHARLINE -- ROLL SCREEN UP -(D) SCAN LINES AND CLEAR
*	SETS CURSORY TO	CHARHEIGHT-1
*	(= LOWEST ROW ON SCREEN	WHICH DOESN'T CHOP OFF PART OF A ROW AT	THE TOP)
*
ROLLUPCHARLINE	EQU     *
	NEGD
	PSHD			SAVE # SCAN LINES TO CLEAR
	JSR	MODIFYSCREENSHIFT GO SHUFFLE THE DISPLAY BUFFER
	LDD	,S		RESTORE	# LINES	TO CLEAR
	LDA	#NBROW
	MUL
	NEGD
	LDX	#SCREENTOP
	LEAX	D,X		= address of 1st screen	line to	clear
	PULD			= # lines to clear
	JSR	CLEARLINES	GO ZERO	THEM
	LDD	#CHARHEIGHT-1+(SCREENHEIGHT-(SCREENHEIGHT/CHARHEIGHT)*CHARHEIGHT)
*				SET NEW	CURSOR POSITION...
	STD	CURSORY		TO TOP OF BOTTOM CHARACTER LINE
	RTS			WHEW! ALL DONE
	PAGE
	 org   (*//$100)*$100	       org to next convenient page (debug only)
*	MAKESPACE -- ROLLS SCREEN UP FOR OBJECT
*	DIMENSIONS: (X)	IS SIZE	IN X ($1FF IS MAXIMUM!)
*	(D) IS SIZE IN Y
*	ADJUSTS	CURSORY	UP APPROPRIATELY...
*	IF SCREEN IS ROLLED
*	CAUSE ERROR IF OBJECT WILL GO OFF RIGHT	HAND SIDE OF SCREEN!
*
MAKESPACE	EQU     *
	STX	DELTAX		FOR CONVENIENCE	TO THE CALLING ROUTINES
	STD	DELTAY
	SEC			COMPUTE	- # HORZ LINES LEFT BELOW OBJECT
	SBCB	CURSORY+1
	SBCA	CURSORY
	BLS	MAKESPACE1	GO IF ZERO OR MORE LINES LEFT
	JSR	MODIFYSCREENSHIFT OBJECT WILL GO OFF SCREEN, ROLL TO MAKE SPACE
*	NOW CLEAR THE SCREEN SPACE
MAKESPACE1	EQU     *
	LDD	CURSORX		COMPUTE	WHERE CURSORX WILL BE...
	ADDD	DELTAX		AFTER DRAWING IS COMPLETE
	if      0
	CMPD	#SCREENWIDTH-1	ENOUGH SPACE TO	RIGHT ?
	BLS	MAKESPACE2	YES, STORE NEW VALUE FOR X AND QUIT
	JMP	ERROR		WELL, YOU FIGURE THIS OUT
	fin
MAKESPACE2	EQU     *
	STD	NEWX		STORE NEW VALUE	FOR CURSORX
	RTS
	 page
	 org   (*//$100)*$100	       org to next convenient page (debug only)
*	DRAWBLANKLINE -- DRAWS A BLANK HORIZONTAL LINE
*	TARGETLEFT POINTS TO 1ST SCREEN	BYTE
*	LEFTEND	CONTAINS LEFT HAND END OF LINE MASK
*	PWIDTH CONTAINS	WIDTH OF LINE IN BYTES
*	RIGHTEND CONTAINS RIGHTMOST MOST BYTE OF LINE MASK
*	IF ONLY	ONE BYTE IS TO BE MODIFIED,
*	THEN LEFTEND = BYTE CONTENT MASK,...
*	     AND RIGHTEND MUST BE ZERO
*
DRAWBLANKLINE	EQU     *
	LDA	CURRENTBACKGROUND IS BACKGROUND	1's or 0's?
	BNE	DRAWSOLIDLINE	B/ BACKGROUND is 1's
	LDU	TARGETLEFT	GET POINTER TO LEFTMOST	BYTE OF	LINE
	LDB	PWIDTH		GET WIDTH OF HORIZONTAL	LINE
	LDAA	LEFTEND		GET LEFTMOST BYTE OF LINE
	COMA			MAKE MASK OF BITS TO RETAIN
	ANDA	0,U		COMBINE	(A) WITH SCREEN	BYTE
	STAA	,U+
	DECB			ALL BYTES IN ROW HIT YET ?
	BEQ	DRAWBLANKRTS	B/ SPECIAL ONE BYTE CASE
	DECB			TWO BYTE WIDE BLANK REGION ?
	BEQ	DRAWBLANKLAST	B/ yes,	go handle last byte
	CLRA			GET ALL	0'S PATTERN
DRAWBLANKLOOP	EQU     *
	STA	,U+		COMBINE	(A) WITH SCREEN	BYTE
	DECB			ALL BYTES IN ROW HIT YET ?
	BNE	DRAWBLANKLOOP	NO
DRAWBLANKLAST ;	re-enter here to handle	two byte wide blank region
	LDAA	RIGHTEND	GET LAST BYTE BIT PATTERN
	COMA			MAKE MASK OFEBITS TO RETAIN
	ANDA	0,U		AND DUMP INTO SCREEN MEMORY
	STAA	0,U
DRAWBLANKRTS
	RTS

DRAWSOLIDLINE	EQU     *
	LDU	TARGETLEFT	GET POINTER TO LEFTMOST	BYTE OF	LINE
	LDB	PWIDTH		GET WIDTH OF HORIZONTAL	LINE
	LDAA	LEFTEND		GET LEFTMOST BYTE OF LINE
	ORAA	0,U		COMBINE	(A) WITH SCREEN	BYTE
	STAA	,U+
	DECB			ALL BYTES IN ROW HIT YET ?
	BEQ	DRAWSOLIDRTS	B/ SPECIAL ONE BYTE CASE
	DECB			TWO BYTE WIDE BLANK REGION ?
	BEQ	DRAWSOLIDLAST	B/ yes,	go handle last byte
	LDAA	#%11111111	GET ALL	1'S PATTERN
DRAWSOLIDLOOP	EQU     *
	STAA	,U+		COMBINE	(A) WITH SCREEN	BYTE
	DECB			ALL BYTES IN ROW HIT YET ?
	BNE	DRAWSOLIDLOOP	NO
DRAWSOLIDLAST ;	re-enter here to handle	two byte wide blank region
	LDAA	RIGHTEND	GET LAST BYTE BIT PATTERN
	ORAA	0,U		AND DUMP INTO SCREEN MEMORY
	STAA	0,U
DRAWSOLIDRTS
	RTS
	PAGE	BLANK REGION
BLANKREGION ; (X) CONTAINS BOX X SIZE, (D) CONTAINS Y SIZE
	BSR	BOXEDGE		GO COMPUTE BOX EDGES AND POINTERS
	BEQ	BLANKREGIONXIT	IF X DIMENSION IS ZERO,	GET OUT!
BLANKLOOP	EQU	*	DRAW ONE ROW OF	A BLANK	BOX
	JSR	DRAWBLANKLINE	GO DRAW	A BLANK	HORIZONTAL LINE
	LDD	TARGETLEFT	NOW ADVANCE DOWN THE SCREEN A ROW
	ADDD	#NBROW
	STD	TARGETLEFT	UPDATE THE BOX LINE LEFT SIDE POINTER
	DEC	DELTAY+1	MORE LINES OF BOX TO DRAW ?
	BNE	BLANKLOOP	YES, GO	DO ANOTHER
	LDX	NEWX		NOW ADVANCE CURSORX PAST THE BOX
	STX	CURSORX
BLANKREGIONXIT	EQU     *
	RTS			AND QUIT
	PAGE	BOXEDGE	SUBROUTINE

*	BOXEDGE	-- SUBROUTINE TO COMPUTE POINTERS AND PIECES OF	BOXES
*	USED BY	SOLIDBOX AND EMPTYBOX
*
BOXEDGE	; (X) =	SIZE IN	X, (D) = SIZE IN Y
	JSR	MAKESPACE	MAKE ENOUGH ROOM ON SCREEN FOR BOX
	JSR	GENCURSORBYTE	FIND UPPER LEFT	HAND CORNER OF BOX
	STX	TARGETLEFT	AND REMEMBER LEFT EDGE OF BOX
	PSHB			SAVE BEGINNING BIT NUMBER
	LDX	#BITMSK		COMPUTE	LEFT MOST BYTE OF BOX
	LDA	B,X		= SPECIFIED BIT	W/ ALL BITS TO RIGHT TURNED ON
	STAA	LEFTCOLUMN	THIS IS	FOR EMPTY BOX SIDES
	ASLA			TURN ON	ALL BITS TO RIGHT OF SPECIFIED BIT
	DECA			NOW WE HAVE LEFTMOST BYTE OF SOLIDBOX
	STAA	LEFTEND		WE MAY NEED THIS A LOT...
	LDAB	NEWX+1		NOW WE MUST FIND RIGHTMOST BYTE	OF EMPTYBOX
	DECB			SINCE BOX DOES NOT ACTUALLY EXTEND TO NEWX
	ANDB	#$7		(JUST LIKE GENCURSORBYTE DOES IT)
	LDA	B,X		RIGHTEND HAS ALL BITS TO LEFT TURNED ON
	STAA	RIGHTCOLUMN	THIS IS	RIGHT SIDE OF EMPTYBOX
	DECA			TURN ON	ALL THE	BITS TO	THE LEFT...
	COMA			OF THE SPECIFIED BIT
	STAA	RIGHTEND	NOW WE HAVE RIGHTMOST BYTE OF SOLIDBOX
	PULB			COMPUTE	WIDTH OF BOX IN	BYTES
	CLRA			= CEILING(DELTAX + LEFT	BIT # )
	ADDB	#7		(CEILING WE GET	BY ROUNDING UP)
	ADDD	DELTAX		(THIS CAN BE AS	LARGE AS 512+7+7)
	LSRD			(DIVIDE	NUMBER OF BITS BY 8)
	LSRD
	LSRD			(B) = WIDTH OF BOX IN BYTES
	STAB	PWIDTH		SAVE WIDTH OF BOX
	CMPB	#1		IS BOX ONE BYTE	WIDE ?
	BNE	BOXIT		NO, DON'T HAVE TO MASK DNDS TOGETHER
	LDAA	LEFTEND		YES, BOX <= 1 BYTE WIDE...
	ANDA	RIGHTEND	SO LEFT	AND RIGHT ENDS OVERLAP
	STAA	LEFTEND		SET LEFT END MASK TO BOX PATTERN
	CLR	RIGHTEND	PREVENT	THIS GUY FROM MUCKING UP THE WORKS
BOXIT	TSTB			LOOK AT	BYTE WIDTH OF BOX
	RTS			AND EXIT WITH CC BIT Z SET
	 org   (*//$100)*$100	       org to next convenient page (debug only)
	 rmb   1		       skip over $3000 to leave	loader alone
	PAGE	DRAW SOLID BOX
	 org   (*//$100)*$100	       org to next convenient page (debug only)
SOLIDBOX ; (X) CONTAINS	BOX X SIZE, (D)	CONTAINS Y SIZE
	BSR	BOXEDGE		GO COMPUTE BOX EDGES AND POINTERS
	BEQ	SOLIDBOXIT	IF X DIMENSION IS ZERO,	GET OUT!
SOLIDLOOP	EQU	*	DRAW ONE ROW OF	A SOLID	BOX
	JSR	DRAWHORZLINE	GO DRAW	A SOLID	HORIZONTAL LINE
	LDD	TARGETLEFT	NOW ADVANCE DOWN THE SCREEN A ROW
	ADDD	#NBROW
	STD	TARGETLEFT	UPDATE THE BOX LINE LEFT SIDE POINTER
	DEC	DELTAY+1	MORE LINES OF BOX TO DRAW ?
	BNE	SOLIDLOOP	YES, GO	DO ANOTHER
	LDX	NEWX		NOW ATVANCE CURSORX PAST THE BOX
	STX	CURSORX
SOLIDBOXIT	EQU     *
	RTS			AND QUIT
	PAGE	DRAW EMPTY BOX
	 org   (*//$100)*$100	       org to next convenient page (debug only)
EMPTYBOX ; (X) CONTAINS	BOX X SIZE, (D)	CONTAINS Y SIZE
	CPX	#1		A ONE BIT WIDE BOX ?
	BEQ	SOLIDBOX	B/ YES,	THIS WILL WORK BETTER AS SOLIDBOX
	JSR	BOXEDGE		COMPUTE	BOX EDGES AND POINTERS
	BEQ	EMPTYBOXIT	QUIT IF	BOX IS ZERO BYTES WIDE
	JSR	DRAWHORZLINE	GO DRAW	TOP OF BOX
	DEC	DELTAY+1	IS BOX ONLY ONE	ROW DEEP ?
	BEQ	EMPTYBOXIT	YES, GET OUT NOW !
EMPTYLOOP	EQU     *
	LDU	TARGETLEFT	ADVANCE	POINTER...
	LEAU	NBROW,U		 DOWN SCREEN...
	STU	TARGETLEFT	  ONE LINE
	DEC	DELTAY+1	ON LAST	LINE OF	BOX ?
	BEQ	EMPTYLAST	YES, GO	DRAW A SOLID LINE
	LDAA	LEFTCOLUMN	INSERT LEFT SIDE OF BOX
	JSR	[WRITEATOSCREEN]
	LDB	PWIDTH		COMPUTE	RIGHT END POINTER
	LEAU	B,U		= LEFT END + PICTUREWIDTH - 1
	LEAU	-1-1,U		IN SAME	ROW (EXTRA -1 OFFSETS AUTOINC...
	LDAA	RIGHTCOLUMN	    IN WRITEATOSCREEN)
	JSR	[WRITEATOSCREEN]
	BRA	EMPTYLOOP

EMPTYLAST	EQU     *
	JSR	DRAWHORZLINE	GO DRAW	A SOLID	HORIZONTAL LINE
EMPTYBOXIT	EQU     *
	LDX	NEWX		NOW ADVANCE CURSORX PAST THE BOX
	STX	CURSORX
	RTS			AND QUIT
	page
*	DRAWHORZLINE --	DRAWS A	HORIZONTAL LINE
*	TARGETLEFT POINTS TO 1ST SCREEN	BYTE
*	LEFTEND	CONTAINS LEFT HAND END OF LINE MASK
*	PWIDTH CONTAINS	WIDTH OF LINE IN BYTES
*	RIGHTEND CONTAINS RIGHTMOST MOST BYTE OF LINE
*	IF ONLY	ONE BYTE IS TO BE MODIFIED,
*	LEFTEND	= BYTE CONTENTS...
*	AND RIGHTEND MUST BE ZERO
*
DRAWHORZLINE	EQU     *
	LDU	TARGETLEFT	GET POINTER TO LEFTMOST	BYTE OF	LINE
	LDAB	PWIDTH		GET WIDTH OF HORIZONTAL	LINE
	LDAA	LEFTEND		GET LEFTMOST BYTE OF LINE
	JSR	[WRITEATOSCREEN] COMBINE (A) WITH SCREEN BYTE
	DECB			ALL BYTES IN ROW HIT YET ?
	BEQ	DRAWHORZLINERTS	B/ YES,	GET OUT!
	DECB			2 BYTE WIDE PATTERN ?
	BEQ	DRAWHORZLINERIGHTMOST B/ YES, GO HANDLE
DRAWHORZLOOP	EQU     *
	LDAA	#%11111111	GET ALL	1'S PATTERN
	JSR	[WRITEATOSCREEN] COMBINE (A) WITH SCREEN BYTE
	DECB			ALL BYTES IN ROW HIT YET ?
	BNE	DRAWHORZLOOP	NO
DRAWHORZLINERIGHTMOST ;	re-enter here if box is	only two bytes wide
	LDAA	RIGHTEND	GET LAST BYTE BIT PATTERN
	JSR	[WRITEATOSCREEN] AND DUMP INTO SCREEN MEMORY
DRAWHORZLINERTS
	RTS
	PAGE	CURSOR HANDLING
	 org   (*//$100)*$100	       org to next convenient page (debug only)
CURSOR	EQU     *
	FDB	6		X SIZE
	FDB	8		Y SIZE
	FCB	%11111100	DOT MATRIX
	FCB	%11111100
	FCB	%11111100
	FCB	%11111100
	FCB	%11111100
	FCB	%11111100
	FCB	%11111100
	FCB	%11111100


SPLAT	EQU	*		DRAW PICTURE AT	(X) IGNORING EDGES OF SCREEN
*				(A,B) POINT TO (X,Y) POSITION ON SCREEN
	STD	TEMPX		SAVE POINTER TO	(X,Y) POSITION
	STX	PICTURE		SAVE POINTER TO	PICTURE
	LDD	PICTYSIZ,X	GET Y PICTURE SIZE
	STD	DELTAY		AND SAVE IT
	LDX	PICTXSIZ,X	GET X PIOTURE SIZE
	STX	DELTAX		AND SAVE IT
	BSR	SPLAT2		PUSH RETURN ADDRESS ON STACK FIRST
	STX	TARGETLEFT	TO BE COMPATIBLE WITH DRAWPICTURE
	JMP	SPLAT1		GO FINISH DRAWING THE PICTURE

SPLAT2	LDX	TEMPX		GET POINTER TO (X,Y) POSITION
	LDD	PICTYSIZ,X	GET Y POSITIFN
	PSHD			PUSH FOR GENCURSORBYTE ENTRY
	LDD	PICTXSIZ,X	GET X POSITION TO (A,B)
	JMP	GENCURSOR1	GO COMPUTE SCREEN ADDRESS
	PAGE	DOWNLOAD FROM HOST
SELECTEORMODE EQU *
	BSR	SETUPWRITE
	EORA	,U
	STAA	,U+
	RTS

SELECTIORMODE	EQU     *
	BSR	SETUPWRITE
	ORAA	,U
	STAA	,U+
	RTS

SELECTANDMODE	EQU     *
	BSR	SETUPWRITE
	COMA
	ANDA	,U
	STAA	,U+
	RTS

SETUPWRITE	EQU     *
	PULX			POINTER	TO SUBROUTINE TO COPY
	LDD	WRITEATOSCREEN GET OLD DISPLAY MODE
	STX	WRITEATOSCREEN REMEMBER	NEW DISPLAY MODE
	RTS			ALL DONE, GET OUT!

; Logically, this is what WRITEATOSCREEN is:
; WRITEATOSCREEN ; write bit pattern in	(A) to screen at (X)
;	(A) placed on screen according to current display mode (XOR, IOR, AND)
;	Current	display	mode selected by changing 1st opcode byte(s)
;	of this	routine, which is in page zero for speed-of-access.
;	NOP			this is	changed	to COMA	for AND	mode
;	EORA	,U		combine	bytes (changed to ORA for IOR mode)
;	STA	,U+		store byte onto	screen,	advance	pointer
;	RTS
	PAGE
*
*	HOMEUP -- SET CURSOR TO	TOP LEFT CORNER	OF SCREEN [(0,0) Char cursor]
*
HOMEUP	EQU     *
	LDX	#CHARLEFTSIDE	= X POSITION OF	HOME
	LDD	#CHARTOPSIDE	= Y POSITION OF	HOME
	JMP	SETCURSORXY
*

ERASETOEOL ; erase to end of line
	LDD	CURSORX		save current cursor position
	PSHD
	NEGD			compute	distance from cursor to	side of	screen
	ADDD	#SCREENWIDTH
	TFR	D,X		= width	of box to blank
	LDD	#CHARHEIGHT	= height of box	to blank
	JSR	BLANKREGION	make region empty
	PULD			set cursorx back to original value
	STD	CURSORX
	RTS			all done!

CURSORTOGGLE ; EOR CURSOR DISPLAY INTO SCREEN AT CURSOR	LOCATION
	COM	CURSORON	remember whether cursor	present	on screen
	JSR	SelectEORMode	so successive passes install/erase cursor
	; also,	we want	EOR mode in case Cursor	sits on	top of some char
	PSHD			remember old display mode
	LDA	#$7F		rubout is cursor blotch
	JSR	DISPLAYCHAR
	LDD	CURSORX		backup cursor to point before display blotch
	SUBD	#CHARWIDTH
	STD	CURSORX
	PULX			restore	current	display	mode
	STX	WRITEATOSCREEN
	RTS

	END
