;
;   Number Nine Revolution 512x8 
;   support routines for raster oriented graphics
;
;   Tim Krauskopf	  July 1986
;	Modified by
;		Quincey Koziol	January 1989
;
;   National Center for Supercomputing Applications, University of Illinois
;   153 Water Resources Building
;   605 E. Springfield Ave.
;   Champaign, IL  61820
;   (217)244-0072
;
;
	TITLE	  NUMBER 9 GRAPHICS SUPPORT
X	EQU	6
.model	large
.code
;	INCLUDE DOS.MAC
;	SETX
;	PSEG
	PUBLIC	_PUTMAP9,_NO9LINE,_NO9PT,_OUTLINE9,_MAKECUR9,_BALL9
	PUBLIC	_NO9BLOCK,_INVERSE9,_INVERT9,_LINENO9,_CIRCLE9,_INCIRC9
	PUBLIC	_SHOWPAL9,_NOPAL9
;
SETBANK	MACRO
	LOCAL	NO706
	LOCAL	NO705	
	LOCAL	OKBANK		; A MACRO TO SET THE BANK FOR THE LINE OF THE NO9 MONITOR
						; BX MUST CONTAIN THE Y POSITION
	MOV	AX,BX		; y location on screen
	MOV	CL,7		; divide by 128
	SHR	AX,CL
	MOV	CL,AL		; make a copy
	CMP	AL,CS:BANK	; is it the same bank?
	JZ	OKBANK

	MOV	CS:BANK,AL	; bank will be this one
	MOV	DH,00H		; default, might be changed
	AND	AL,02H		; is high bit on?
	JZ	NO706

	MOV	DH,0FFH		;  setting for new bank
NO706:
	MOV	DL,00H		; default setting for 705
	MOV	AL,CL		; get back copy
	AND	AL,01H		; is low bit on?
	JZ	NO705

	MOV	DL,0FFH		; other portion of new bank
NO705:
	MOV	DI,0705H	; where bank reg is
	MOV	AX,DX
	STOSW			; sets both bytes, lo then hi
;
;   READY TO PUT THE LINE
;
OKBANK:
	ENDM			; END OF THE COMPUTE BANK MACRO
;
;  take three arrays of color table entries and transfer them to the
;  board's registers
;
;  usage:  putmap9(rmap,gmap,bmap);
;
_PUTMAP9	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	AX,[BP+X+2]
	MOV	DS,AX			; where to get maps (seg)
	MOV	SI,[BP+X]		; where to get red
	MOV	AX,0C000H		; control seg for #9
	MOV	ES,AX
	MOV	DI,0100H		; red map
	MOV	CX,256			; length of map
	REP	MOVSB			; mov red
;
	MOV	SI,[BP+X+4]
	MOV	DI,0200H		; green map
	MOV	CX,256
	REP	MOVSB
;
	MOV	SI,[BP+X+8]		; blue map
	MOV	DI,0300H	
	MOV	CX,256
	REP	MOVSB
;
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
_PUTMAP9	ENDP
;
;  Transfer line to #9 screen, one byte per pixel
;
;   usage : no9line(x,y,buf,xoff,nbytes)
;
_NO9LINE	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI
	MOV	AX,0C000H	; control regs
	MOV	ES,AX

	MOV	AX,[BP+X+6]	; ds of buffer
	MOV	DS,AX
	MOV	BX,[BP+X+2]	; y location on screen
	SETBANK			; CALL MACRO TO SET THE CORRECT MEMORY BANK FOR THE Y POSITION
	MOV	AX,0A000H	; data buffer
	MOV	ES,AX
	MOV	SI,[BP+X+4]	; where data will come from
	MOV	AX,[BP+X+8]	; GET THE X OFFSET INTO THE ARRAY
	CMP	AX,0		; CHECK FOR NEGATIVE OFFSET
	JGE	OKSIGN		; JUMP AROUND FIXING THE WINDOW
	NEG	AX			; TAKE THE OPPOSITE VALUE
	ADD AX,[BP+X]	; AND ADD IT TO THE POSITION ON THE SCREEN
	MOV	[BP+X],AX	; AND RE-STORE THE POSITION
	MOV	AX,[BP+X+8]	; GET THE NEGATIVE OFFSET AGAIN
	ADD	AX,[BP+X+10]	; REDUCE THE NUMBER OF BYTES TO COPY TO THE SCREEN
	MOV	[BP+X+10],AX	; AND STORE THE NUMBER OF BYTES AGAIN
OKSIGN:
	ADD	SI,AX		; ADD THE OFFSET TO THE OFFSET OF THE ARRAY
;
	MOV	AX,[BP+X+2]	; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X]	; x value of where on screen added in
	MOV	DI,AX		; prepare for movs
	MOV	CX,[BP+X+10]	; how many bytes?
	SHR	CX,1						; CHECK WHETHER THIS CAN BE WORD MOV'ED OR NOT
	JC	DOBYTES						; NO, CANNOT USE WORD MOVE
	REP	MOVSW						; MOVE WORDS
	JMP	SHORT	DONECOPY			; JUMP AROUND THE BYTE COPY

DOBYTES:
	MOV	CX,[BP+X+10]				; GET THE COUNT OF BYTES TO MOVE
	REP	MOVSB						; MOV THE MEMORY

DONECOPY:
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
BANK	DB	0FFH		; current bank number
_NO9LINE	ENDP

;
;	showpal9(&palstore,pal_xoff,pal_yoff);
;
_SHOWPAL9		PROC	FAR
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	CX,16		; COUNT THE NUMBER OF LINES TO SAVE
	PUSH	CX		; AND SAVE THE COUNT
SHOWTOP:
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	MOV	BX,[BP+X+6]	; y location on screen
	INC	WORD PTR [BP+X+6]	; GET THE Y VALUE OF THE NEXT LINE
	SETBANK			; CALL MACRO TO SET THE CORRECT MEMORY BANK FOR THE Y POSITION
	MOV	AX,0A000H	; data buffer
	MOV	DS,AX
	MOV	AX,BX		; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X+4]	; ADD IN THE X OFFSET
	MOV	SI,AX		; prepare for movs
	MOV	DI,[BP+X]	; GET OFFSET OF ARRAY
	MOV	AX,[BP+X+2]	; GET SEGMENT OF STORAGE ARRAY
	MOV	ES,AX			
	MOV	CX,0		; how many bytes?
ZING:
	MOVSB			; SAVE THE OLD VALUE
	DEC	SI			; GO BACK TO PUT THE PALETTE IN MEMORY
	MOV	DS:BYTE PTR [SI],CL	; PUT THE PALETTE VALUE THERE
	INC	SI
	INC	CX			; INCREMENT THE LOOP COUNTER
	CMP	CH,1		; CHECK FOR THE END OF THE LINE
	JNE	ZING		; FINISH THE PALETTE  FOR THAT LINE

	POP	CX			; RECOVER THE COUNT OF LINES
	DEC	CX			; 
	PUSH	CX		; KEEP THE COUNT AROUND STILL
	MOV	[BP+X],DI	; SAVE MODIFIED OFFSET
	CMP	CX,0		; CHECK FOR THE COUNT BEING DONE
	JNE	SHOWTOP

	POP	CX		; GET RID OF EXTRANEOUS PUSH

	POP	DI
	POP	SI
	POP	ES
	POP	DS
	POP	BP
	RET
_SHOWPAL9	ENDP
;
;	nopal9(&palstore,pal_xoff,pal_yoff);
;
_NOPAL9		PROC	FAR
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	CX,16		; THE NUMBER OF LINES TO REPLACE
	PUSH	CX		; SAVE THE NUMBER OF LINES
NOTOP:
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	MOV	BX,[BP+X+6]	; y location on screen
	INC	WORD PTR [BP+X+6]	; MAKE Y POSITION FOR NEXT LINE
	SETBANK			; CALL MACRO TO SET THE CORRECT MEMORY BANK FOR THE Y POSITION

	MOV	AX,0A000H	; data buffer
	MOV	ES,AX
	MOV	AX,[BP+X+2]	; ds of buffer
	MOV	DS,AX
	MOV	SI,[BP+X]	; where data will come from

	MOV	AX,BX		; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X+4]	; x value of where on screen added in
	MOV	DI,AX		; prepare for movs

	MOV	CX,256		; how many bytes?
ZOOM:
	REP	MOVSB

	POP	CX			; RECOVER THE COUNT OF LINES
	DEC	CX			; 
	PUSH	CX		; KEEP THE COUNT AROUND STILL
	MOV	[BP+X],SI	; SAVE MODFIED OFFSET
	CMP	CX,0		; CHECK FOR THE COUNT BEING DONE
	JNE 	NOTOP

	POP	CX			; GET RID OF EXTRANEOUS CX PUSH
	
	POP	DI
	POP	SI
	POP	ES
	POP	DS
	POP	BP
	RET
_NOPAL9	ENDP
;
;	no9pt(x,y,color);
;
_NO9PT		PROC	FAR
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	DI
	MOV	AX,0C000H	; control regs
	MOV	ES,AX

	MOV	BX,[BP+X+2]	; GET LINE TO COPY SCREEN BACK ONTO
	SETBANK

	MOV	AX,0A000H	; data buffer
	MOV	ES,AX

	MOV	AX,[BP+X+2]	; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X]	; ADD IN THE X OFFSET

	MOV	DI,AX		; prepare for movs
	MOV	AL,[BP+X+4]	; GET THE VALUE TO PUT THERE

	STOSB			; PUT COLOR ON THE SCREEN

	POP		DI
	POP		ES
	POP		DS
	POP	BP
	RET
_NO9PT	ENDP

Y_COUNT	DW	0		; THE NUMBER OF Y LINES TO INVERT
;
;  Invert A BOX ON THE SCREEN
;
;   usage : outline9(x1,y1,x2,y2)
;
_OUTLINE9	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	AX,[BP+X+2]	; GET FIRST Y VALUE
	CMP	AX,[BP+X+6]	; COMPARE WITH THE SECOND Y - VALUE
	JLE	CHECKX		; OK ORDER GOTO CHECKING THE X VALUES
	MOV	CX,AX		; SWAP THE TWO VALUES
	MOV	AX,[BP+X+6]	;
	MOV	[BP+X+2],AX	;
	MOV	AX,CX		;
	MOV	[BP+X+6],AX	;
CHECKX:
	MOV	AX,[BP+X]	; GET FIRST X VALUE
	CMP	AX,[BP+X+4]	; COMPARE WITH THE SECOND X - VALUE
	JLE	MAKELEN		; OK ORDER GOTO COMPUTING THE LENGTHS
	MOV	CX,AX		; SWAP THE TWO VALUES
	MOV	AX,[BP+X+4]	;
	MOV	[BP+X],AX	;
	MOV	AX,CX		;
	MOV	[BP+X+4],AX	;
MAKELEN:			; COMPUTE THE X AND Y WIDTHS FOR THE BOX TO BE INVERTED
	MOV	AX,[BP+X+4]	; GET THE LARGER OF THE TWO X VALUES
	SUB	AX,[BP+X]	; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
	MOV	[BP+X+4],AX	; STORE IT IN THE OLD LOCATION FOR THE 2ND X VALUE
	MOV	AX,[BP+X+6]	; GET THE LARGER OF THE TWO Y VALUES
	SUB	AX,[BP+X+2]	; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
	SUB	AX,1		; SUBTRACT TWO FOR THE TOP AND BOTTOM EDGES
	CMP	AX,0		; CHECK IF IT IS LESS THAN ZERO
	JG 	POSITIVE	; JUMP AROUND ZEROING THE ACC.
	MOV	AX,0
POSITIVE:
	MOV	[BP+X+6],AX	; STORE IT IN THE OLD LOCATION FOR THE 2ND Y VALUE
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	MOV	BX,[BP+X+2]	; GET THE Y LOCATION FOR THE TOP LINE
	SETBANK			; CALL MACRO TO SET THE CORRECT MEMORY BANK FOR THE Y POSITION
	MOV	AX,0A000H	; SET THE DATA BUFFER
	MOV	ES,AX
	MOV	AX,[BP+X+2]	; GET THE Y POSITION FOR THE TOP LINE AGAIN
	MOV	CL,9
	SHL	AX,CL
	ADD	AX,[BP+X]	; ADD IN THE X OFFSET
	MOV	DI,AX		; STORE THE OFFSET
	MOV	CX,[BP+X+4]	; THE NUMBER OF BYTES TO INVERT
	INC	CX
BLASTA:
	MOV	AL,ES:[DI]	; GET THE BYTE TO INVERT
	NOT	AL		; INVERT THE BYTE
	MOV	ES:[DI],AL	; REPLACE THE BYTE
	INC	DI		; GO TO THE NEXT BYTE
	LOOP	BLASTA		; FINISH THE LINE OUT

	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	ADD	BX,[BP+X+6]	; ADD IN THE Y SIZE TO GET TO THE LAST LINE
	ADD	BX,1		;
	SETBANK			; CALL MACRO TO SET THE CORRECT MEMORY BANK FOR THE Y POSITION
	MOV	AX,0A000H	; SET THE DATA BUFFER
	MOV	ES,AX
	MOV	AX,BX		; GET THE Y POSITION FOR THE TOP LINE AGAIN
	MOV	CL,9
	SHL	AX,CL
	ADD	AX,[BP+X]	; ADD IN THE X OFFSET
	MOV	DI,AX		; STORE THE OFFSET
	MOV	CX,[BP+X+4]	; THE NUMBER OF BYTES TO INVERT
	INC	CX
BLASTB:
	MOV	AL,ES:[DI]	; GET THE BYTE TO INVERT
	NOT	AL			; INVERT THE BYTE
	MOV	ES:[DI],AL	; REPLACE THE BYTE
	INC	DI			; GO TO THE NEXT BYTE
	LOOP	BLASTB	; FINISH THE LINE OUT

	MOV	CX,[BP+X+6]	; GET THE NUMBER OF LINES IN THE MIDDLE
	MOV	Y_COUNT,CX	; STORE IT IN THE PROPER PLACE
OUTTOP:
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	INC	WORD PTR [BP+X+2]	; INCREMENT THE LINE TO INVERT
	MOV	BX,[BP+X+2]	; GET THE LINE TO MODIFY
	SETBANK			; CALL MACRO TO SET THE CORRECT MEMORY BANK FOR THE Y POSITION
	MOV	AX,0A000H	; SET THE DATA BUFFER
	MOV	ES,AX
	MOV	AX,[BP+X+2]	; GET THE Y POSITION FOR THE TOP LINE AGAIN
	MOV	CL,9
	SHL	AX,CL
	ADD	AX,[BP+X]	; ADD IN THE X OFFSET
	MOV	DI,AX		; STORE THE OFFSET
	MOV	AL,ES:[DI]	; GET THE BYTE TO INVERT
	NOT	AL			; INVERT THE BYTE
	MOV	ES:[DI],AL	; REPLACE THE BYTE
	ADD	DI,[BP+X+4]	; GET TO THE END OF THE LINE		
	MOV	AL,ES:[DI]	; GET THE BYTE TO INVERT
	NOT	AL			; INVERT THE BYTE
	MOV	ES:[DI],AL	; REPLACE THE BYTE
	DEC	Y_COUNT		; DECREMENT THE COUNT
	CMP	Y_COUNT,0	; CHECK FOR THE END OF THE BOX
	JG	OUTTOP		; JUMP BACK TO THE BEGINNING

	POP		DI
	POP		ES
	POP		DS
	POP	BP
	RET
_OUTLINE9	ENDP

X_SIZE	DW	16		; X WIDTH OF THE CURSOR
Y_SIZE	EQU	32		; TWICE THE Y HEIGHT OF THE CURSOR
X_HOT	EQU	7		; HORIZONTAL HOT SPOT FOR THE CURSOR
Y_HOT	EQU	7		; VERTICAL HOT SPOT FOR THE CURSOR
X_START	DW	?		; THE X POSITION TO START THE ARRAY ON
;
;	EACH BIT PLACE IN THE CURSOR ARRAY STANDS FOR A BYTE ON THE SCREEN
;	IF THE BIT IS ON, THEN THAT BYTE ON THE SCREEN WILL BE INVERTED
;	IF NOT, THEN THE BYTE WILL BE UNTOUCHED.
;	THE NUMBER OF WORDS FOR THE CURSOR ARRAY, AND THE NUMBER OF BITS
;	IN EACH IS CONTROLLED BY THE X_SIZE AND Y_SIZE VARIABLES.
CURSOR	LABEL	WORD		; LABEL FOR THE BEGINNING OF THE CURSOR ARRAY
		DW	0000000000000000B
		DW	0000000000000000B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0011111111111100B
		DW	0011111111111100B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0000000110000000B
		DW	0000000000000000B
		DW	0000000000000000B
;
;
;	Routine to make a cursor on the screen
;	makecur9(x,y);
;
_MAKECUR9	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	AX,[BP+X+2]	; GET THE Y VALUE TO MODIFY FOR THE HOT SPOT
	SUB	AX,Y_HOT	; SUBTRACT THE HOT SPOT VALUE
	MOV	[BP+X+2],AX	; REPLACE THE Y VALUE

	MOV	AX,512		; GET THE SCREEN SIZE
	SUB	AX,[BP+X]	; SUBTRACT THE X COOR.
	SUB AX,X_SIZE	; SUBTRACT THE SIZE OF THE CURSOR
	CMP	AX,0		; CHECK TO SEE IF THE CURSOR WILL OVERLAP THE SIDE
	JL	OK_COOR
	ADD	AX,X_SIZE	; FIGURE OUT THE PROPER CURSOR SIZE
	MOV	X_SIZE,AX	; REPLACE CURSOR SIZE
OK_COOR:
	MOV	AX,[BP+X]	; GET THE X VALUE TO MODIFY FOR THE HOT SPOT
	SUB	AX,X_HOT	; SUBTRACT THE HOT SPOT VALUE
	MOV	[BP+X],AX	; REPLACE THE X VALUE

	MOV	X_START,0	; INITIALIZE THE X_START TO BE IN THE 0 POSITION
	MOV	SI,0		; INITIALIZE THE Y COUNTER
CURTOP:
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	MOV	BX,[BP+X+2]	; GET LINE TO COPY SCREEN BACK ONTO
	CMP	BX,0		; CHECK FOR NEGATIVE COORDINATES
	JL	CUREND		; IF NEGATIVE COORDINATES THEN JUMP TO END OF LOOP
	SETBANK

	MOV	AX,0A000H	; data buffer
	MOV	ES,AX

	MOV	DX,X_START	; INITIALIZE THE X COUNTER
	MOV	BX,CURSOR[SI]	; GET THE CURRENT CURSOR INFORMATION
	MOV	CX,X_START	; GET THE INITIAL NUMBER OF BITS TO SHIFT THE ARRAY
	SHL	BX,CL		; SHIFT THE ARRAY THAT MANY BYTES
TRYAGAIN:
	MOV	AX,[BP+X]	; GET THE X POSITION
	CMP	AX,0		; CHECK FOR NEGATIVE POSITION
	JGE	OKFINE		; NOT A NEGATIVE VALUE
	INC	WORD PTR [BP+X]	; INCREMENT THE X POSITION
	INC	DX			; AND THE POSITION IN THE ARRAY
	INC	WORD PTR X_START	; INCREMENT THE POSITION TO START IN THE ARRAY FOR NEXT LOOP THRU
	SHL	BX,1		; GET RID OF A BIT OF THE CURSOR INFORMATION
	JMP	TRYAGAIN	; JUMP BACK TO TRY FOR ANOTHER X POSITION
OKFINE:
	MOV	AX,[BP+X+2]	; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X]	; ADD IN THE X OFFSET
	MOV	DI,AX		; prepare for movs

LOOPTOP:
	SHL	BX,1		; GET THE BIT FOR THIS CURSOR POSITION
	JNC	LOOPBOT		; IF IT NOT SET THEN JUMP TO BOTTOM OF LOOP
	MOV	AL,ES:[DI]	; GET THE BYTE TO INVERT
	NOT	AL			; INVERT THE BYTE
	MOV	ES:[DI],AL	; REPLACE THE INVERTED BYTE
LOOPBOT:
	INC	DI			; INCREMENT FOR NEXT BYTE ON THE SCREEN
	INC	DX			; INCREMENT THE POSITION IN THE ARRAY
	CMP	DX,X_SIZE	; CHECK TO SEE IF THE END OF THE LINE HAS BEEN FOUND
	JNE	LOOPTOP		; IF NOT END THEN JUMP TO BEGINNING OF THE LOOP

CUREND:
	INC	WORD PTR [BP+X+2]	; INCREMENT Y VALUE FOR THE NEXT LINE
	INC	SI			; INCREMENT THE Y POSITION IN THE ARRAY
	INC	SI
	CMP	SI,Y_SIZE	; CHECK TO SEE IF THE BOOTOM OF THE ARRAY HAS BEEN REACHED
	JE	KLUDGE		; JUMP AROUND JUMP BACK IF AT END
	JMP	CURTOP		; IF NOT THEN JUMP TO BEGINNING OF A NEW LINE
KLUDGE:

	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
_MAKECUR9	ENDP

BALLX_SIZE	EQU	8		; X WIDTH OF THE CURSOR
BALLY_SIZE	EQU	8		; Y HEIGHT OF THE CURSOR
BALL	LABEL	BYTE		; LABEL FOR THE BEGINNING OF THE CURSOR ARRAY
		DB	00111100B
		DB	01111110B
		DB	11111111B
		DB	11111111B
		DB	11111111B
		DB	11111111B
		DB	01111110B
		DB	00111100B
;
;
;	Routine to make a cursor on the screen
;	ball9(x,y);
;
_BALL9		PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	X_START,0	; INITIALIZE THE X_START TO BE IN THE 0 POSITION
	MOV	SI,0		; INITIALIZE THE Y COUNTER
BALLTOP:
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	MOV	BX,[BP+X+2]	; GET LINE TO COPY SCREEN BACK ONTO
	CMP	BX,0		; CHECK FOR NEGATIVE COORDINATES
	JL	BALLEND		; IF NEGATIVE COORDINATES THEN JUMP TO END OF LOOP
	SETBANK

	MOV	AX,0A000H	; data buffer
	MOV	ES,AX

	MOV	DX,X_START	; INITIALIZE THE X COUNTER
	MOV	BL,BALL[SI]	; GET THE CURRENT CURSOR INFORMATION
	MOV	CX,X_START	; GET THE INITIAL NUMBER OF BITS TO SHIFT THE ARRAY
	SHL	BL,CL		; SHIFT THE ARRAY THAT MANY BYTES
BTRYAGAIN:
	MOV	AX,[BP+X]	; GET THE X POSITION
	CMP	AX,0		; CHECK FOR NEGATIVE POSITION
	JGE	BOKFINE		; NOT A NEGATIVE VALUE
	INC	WORD PTR [BP+X]	; INCREMENT THE X POSITION
	INC	DX			; AND THE POSITION IN THE ARRAY
	INC	WORD PTR X_START	; INCREMENT THE POSITION TO START IN THE ARRAY FOR NEXT LOOP THRU
	SHL	BL,1		; GET RID OF A BIT OF THE CURSOR INFORMATION
	JMP	BTRYAGAIN	; JUMP BACK TO TRY FOR ANOTHER X POSITION
BOKFINE:
	MOV	AX,[BP+X+2]	; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X]	; ADD IN THE X OFFSET
	MOV	DI,AX		; prepare for movs

BLOOPTOP:
	SHL	BL,1		; GET THE BIT FOR THIS CURSOR POSITION
	JNC	BLOOPBOT	; IF IT NOT SET THEN JUMP TO BOTTOM OF LOOP
	MOV	AL,ES:[DI]	; GET THE BYTE TO INVERT
	NOT	AL			; INVERT THE BYTE
	MOV	ES:[DI],AL	; REPLACE THE INVERTED BYTE
BLOOPBOT:
	INC	DI			; INCREMENT FOR NEXT BYTE ON THE SCREEN
	INC	DX			; INCREMENT THE POSITION IN THE ARRAY
	CMP	DX,BALLX_SIZE	; CHECK TO SEE IF THE END OF THE LINE HAS BEEN FOUND
	JNE	BLOOPTOP		; IF NOT END THEN JUMP TO BEGINNING OF THE LOOP

BALLEND:
	INC	WORD PTR [BP+X+2]	; INCREMENT Y VALUE FOR THE NEXT LINE
	INC	SI			; INCREMENT THE Y POSITION IN THE ARRAY
	CMP	SI,BALLY_SIZE	; CHECK TO SEE IF THE BOOTOM OF THE ARRAY HAS BEEN REACHED
	JE	BKLUDGE		; JUMP AROUND JUMP BACK IF AT END
	JMP	BALLTOP		; IF NOT THEN JUMP TO BEGINNING OF A NEW LINE
BKLUDGE:

	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
_BALL9	ENDP

X_MAX	DW	?		; X WIDTH OF THE BLOCK
Y_MAX	DW	?		; THE Y HEIGHT OF THE BLOCK
;
;
;	Routine to make a cursor on the screen
;	no9block(&block,x,y,xmax,ymax);
;
_NO9BLOCK	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	AX,[BP+X+10]; GET THE Y MAXIMUM
	MOV	Y_MAX,AX	; STORE THE Y MAXIMUM

	MOV	AX,[BP+X+8]	; GET THE X_MAXIMUM
	MOV	X_MAX,AX	; STORE THE X MAXMIMUM

	MOV	AX,[BP+X]	; GET THE OFFSET OF THE BLOCK
	MOV	SI,AX		; STORE THE OFFSET OF THE ARRAY
	MOV	AX,[BP+X+2]	; GET THE SEGMENT OF THE ARRAY
	MOV	DS,AX		; STORE THE SEGMENT
BLASTBLOCK:
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	MOV	BX,[BP+X+6]	; GET LINE TO COPY SCREEN BACK ONTO
	SETBANK

	MOV	AX,0A000H	; data buffer
	MOV	ES,AX

	MOV	AX,[BP+X+6]	; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X+4]	; ADD IN THE X OFFSET
	MOV	DI,AX		; prepare for movs
	MOV	CX,X_MAX	; GET THE NUMBER OF BYTES TO MOVE
	
	REP	MOVSB		; PUT A HORIZONTAL LINE OF THE BLOCK ON THE SCREEN
	
	INC WORD PTR [BP+X+6]	; INCREMENT THE Y POSITION
	DEC	Y_MAX		; DECREMENT THE COUNTER FOR THE NUMBER OF LINES
	JG	BLASTBLOCK	; JUMP TO TOP OF LOOP TO OUTPUT ANOTHER LINE

	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
_NO9BLOCK	ENDP

;
;
;	Routine to make a cursor on the screen
;	inverse9(x0,y0,width,height);
;
_INVERSE9	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	DI

	MOV	AX,[BP+X+6]; GET THE Y MAXIMUM
	MOV	Y_MAX,AX	; STORE THE Y MAXIMUM

	MOV	AX,[BP+X+4]	; GET THE X_MAXIMUM
	MOV	X_MAX,AX	; STORE THE X MAXMIMUM

INVERSEBLOCK:
	MOV	AX,0C000H	; control regs
	MOV	ES,AX
	MOV	BX,[BP+X+2]	; GET LINE TO COPY SCREEN BACK ONTO
	SETBANK

	MOV	AX,0A000H	; data buffer
	MOV	ES,AX

	MOV	AX,[BP+X+2]	; get y value again
	MOV	CL,9
	SHL	AX,CL		; get 16 bit pointer for this bank
	ADD	AX,[BP+X]	; ADD IN THE X OFFSET
	MOV	DI,AX		; prepare for movs
	MOV	CX,X_MAX	; GET THE NUMBER OF BYTES TO MOVE
INVERSELINE:
	MOV	AL,BYTE PTR ES:[DI]	; GET THE BYTE TO INVERSE
	NOT	AL			; INVERSE THE BYTE
	MOV	BYTE PTR ES:[DI],AL	; REPLACE THE BYTE
	INC	DI
	LOOP INVERSELINE
	
	INC WORD PTR [BP+X+2]	; INCREMENT THE Y POSITION
	DEC	Y_MAX		; DECREMENT THE COUNTER FOR THE NUMBER OF LINES
	JG	INVERSEBLOCK	; JUMP TO TOP OF LOOP TO OUTPUT ANOTHER LINE

	POP	DI
	POP	ES
	POP	DS
	POP	BP
	RET
_INVERSE9	ENDP

_INVERT9		PROC	FAR		; PROCEDURE FOR BRESENHAM'S LINE DRAWING ROUTINE TO XOR THE LINE DATA
	RET
_INVERT9		ENDP

_LINENO9		PROC	FAR		; PROCEDURE FOR BRESENHAM'S LINE DRAWING ROUTINE
	RET
_LINENO9		ENDP

_CIRCLE9		PROC	FAR
	RET
_CIRCLE9		ENDP

_INCIRC9		PROC	FAR
	RET
_INCIRC9		ENDP

;	ENDPS
	END
