;
;  EGA GRAPHICS DRIVER 
;
;  supports raster graphics on the Enhanced Adapter
;
;	  Tim Krauskopf			   Spring 1986
;	Modified by
;		Quincey Koziol	January 1989
;
;  National Center for Supercomputing Applications
;  605 E. Springfield
;  Champaign, IL 61820
;  (217) 244-0074
;
;
		TITLE   EGA GRAPHICS RASTER DRIVER
		NAME	EGA
		INCLUDE DOS.MAC
		SETX
;
;  Define where the registers are
;
SEQ		EQU		03C4H
MAPREG	EQU		2
MAPMASK	EQU		03C5H
GCHIP	EQU		03CEH
DRREG	EQU		3
MODEREG EQU		5
BITREG	EQU		8
BITMASK	EQU		03CFH
;
		DSEG
FLAG	DB	0			; HAVE WE SET REGS UP

MAP_LEFT	DB	?		; BIT MAP FOR LEFT EDGE OF MIDDLE LINES
MAP_RIGHT	DB	?		; BIT MAP FOR RIGHT EDGE OF MIDDLE LINES
MAP_TOPL	DB	?		; BIT MAP FOR TOP & BOTTOM LINES LEFT EDGE
MAP_TOPR	DB	?		; BIT MAP FOR TOP & BOTTOM LINES RIGHT EDGE
RIGHT_EDGE	DW	?		; BYTE OFFSET OF LEFT EDGE
LEFT_EDGE	DW	?		; BYTE OFFSET OF RIGHT EDGE
X_WIDTH		DW	?		; WIDTH OF TOP & BOTTOM LINES IN BYTES
Y_HEIGHT	DW	?		; HEIGHT OF THE ENTIRE OUTLINE
RIGHT_BIT	DW	?		; BIT OFFSET OF RIGHT EDGE
TOP1_BYTE	DW	?		; BYTE OFFSET OF TOP LINE +1
BOTTOM_BYTE	DW	?		; BYTE OFFSET OF BOTTOM LINE
TOP_BYTE	DW	?		; BYTE OFFSET OF TOP LINE
X_OFF		DW	?		; HORIZONTAL OFFSET INTO THE BLOCK BEING PROCESSED
Y_OFF		DW	?		; OFFSET INTO THE BLOCK BEING PROCESSED
X_TEMP		DW	?		; TEMPORARY X VALUE
BLKOFF		DW	?		; THE OFFSET OF A BLOCK PASSED TO EGABLOCK
BLKSEG		DW	?		; THE SEGMENT OF A BLOCK PASSED TO EGABLOCK
		ENDDS

		PSEG
		PUBLIC  _EGAPT,_EGALINE,_EGALINE2,_EGALINEA
		PUBLIC	_INITEGA,_RESETEGA,_EGAPAL,_PUTMAPE;,_OUTLINEE
		PUBLIC	_INVERSEE,_EGABLOCK,_SETTRANS
		PUBLIC	_INVERT10,_LINE10,_CIRCLE10,_INCIRC10

;
;NAME:		PIXELADDR10
;
;CALLER:	AX = Y-COORDINATE
;		BX = X-COORDINATE
;
;RETURNS:	AH = BITMASK
;			BX = BYTE OFFSET IN BUFFER
;			CL = NUMBER OF BITS TO SHIFT LEFT
;			ES = VIDEO BUFFER SEGMENT
;
;
;
BYTESPERLINE	EQU	80
ORIGINOFFSET	EQU	0
VIDEOBUFFERSEG	EQU	0A000H
PIXELADDR10	PROC	NEAR

	MOV		CL, BL
	PUSH	DX

	MOV		DX, BYTESPERLINE
	MUL		DX

	POP		DX
	SHR		BX, 1
	SHR		BX, 1
	SHR		BX, 1
	ADD		BX, AX
	ADD		BX, ORIGINOFFSET

	MOV		AX, VIDEOBUFFERSEG
	MOV		ES, AX

	AND		CL, 7
	XOR		CL, 7
	MOV		AH,	1
	RET

PIXELADDR10	ENDP

TRANSOFF	DW	?		; THE OFFSET OF THE TRANSLATION ARRAY
TRANSSEG	DW	?		; THE SEGMENT OF THE TRANSLATION ARRAY
TRANS_TAB	DB	256 DUP(?)	; ALLOCATE ROOM FOR THE TRANSLATIONS TABLE
;******************************************************************
;  INITEGA
;	use the BIOS to set mode 10 on the EGA board
;
_INITEGA	PROC	FAR
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI
	MOV	AX,0010H		; set to hi-res mode for EGA
	INT	10h				; video
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	RET
_INITEGA	ENDP

_RESETEGA	PROC	FAR
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI
	MOV	AX,3			; set to color character mode
	INT	10h
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	RET
_RESETEGA	ENDP

;*******************************************************************
;  PALETTE 
;	 set one element of the EGA's palette select
;
;  usage:  egapal(reg,setting);
;			 reg (0-15)		EGA's palette regs
;			 setting			one byte, what to write there
;
_EGAPAL	PROC	FAR
	PUSH	BP
	MOV	BP,SP

	MOV	BL,[BP+X]		; register #
	MOV	BH,[BP+X+2]		; value
	MOV	AX,01000H		; set palette element
	INT	10h

	POP	BP
	RET
_EGAPAL	ENDP

;
;	TAKES A TABLE OF PALETTE SETTINGS AND USES BIOS CALL TO PUT THEM INTO THE PALETTE
;	USAGE:	PUTMAPE(&TABLE)
;
_PUTMAPE	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES

	MOV	DX,[BP+X]		; GET THE OFFSET OF THE PALETTE LIST
	MOV	AX,[BP+X+2]		; GET THE SEGMENT OF THE PALETTE LIST
	MOV	ES,AX			; MOVE THE SEGMENT INTO THE PROPER REGISTER
	MOV	AX,01002H		; MOVE THE CODE FOR SETTING ALL PALETTE REGISTERS INTO THE AX
	INT	10H				; DO A VIDEO BIOS CALL TO SET THE PALETTE REGISTERS
		
	POP	ES
	POP	DS
	POP	BP
	RET
_PUTMAPE	ENDP

;*****************************************************************
;  Puts an absolute pixel in the given color
;
;   usage:   egapoint(x,y,color,table)
;			x,y = point location
;			color = integer color number  0 to 255
;			table = translation table of 256 bytes for XLAT
;
;   BUG:  will only write on black background, see egaline for
;		 clearing all four planes before writing to specified planes
;		 in that color
;
_EGAPT	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	ES
	PUSH	DI

	MOV AL,FLAG  
	OR	AL,AL
	JNZ NOSETUP
	CALL	SETUPG		; set up the mask regs
	MOV FLAG,1			; set the flag
NOSETUP:
	MOV CX,TRANSSEG		; get segment of transtable
	MOV BX,TRANSOFF		; get offset of transtable
	MOV	AX,[BP+X+4]		; get the color param = 3rd param
	PUSH DS
	MOV DS,CX			; set ds for the transtable
	XLATB				; pick up translated color
	POP DS
	MOV	DX,MAPMASK
	OUT	DX,AL			; set the mask to this color
	MOV	AX,0A000H
	MOV ES,AX			; set for addressing
	MOV	AX,[BP+X+2]		; get y value 0 < y < 350
	MOV	BX,80
	MUL BX				; multiply by 80 bytes/line
	MOV DI,AX			; put in DI
	MOV AX,[BP+X]		; get x value 0 < x < 640
	MOV BX,AX			; save it
	MOV CL,3
	SHR AX,CL			; divide by 8
	ADD DI,AX			; add it to di = byte offset
;
	MOV CX,BX
	AND CX,0007H		; save only the right three bits
	MOV BL,80H			; here's a bit
	SHR	BL,CL			; move it over some
	MOV DX,BITMASK		; set the mask
	MOV AL,BL			 
	OUT DX,AL			;  send it
;
	MOV	AL,0FFH			; set all bits
	MOV	AH,ES:[DI]		; latch the bytes
	STOSB				; place that bit on bit mask

	POP	DI
	POP	ES
	POP	BP
	RET
_EGAPT	ENDP

SETUPG:
	MOV	DX,GCHIP
	MOV	AL,MODEREG
	OUT	DX,AL			; choose write mode 0
	INC	DX
	MOV	AL,0
	OUT	DX,AL			; clear mode reg to 0
	DEC DX
	MOV	AL,DRREG		; clear function select = Replace
	OUT	DX,AL
	INC DX
	MOV	AL,0h			; clear all
	OUT	DX,AL
;
	MOV	AL,MAPREG		; want to access mapreg from 
	MOV	DX,SEQ			; sequencer set of regs
	OUT	DX,AL
	MOV	AL,BITREG		; want to access bitreg from
	MOV DX,GCHIP		; graphics chip's regs
	OUT	DX,AL
	MOV	DX,BITMASK		; set up the bitmask = no masking
	MOV	AL,0FFH			; all bits on
	OUT	DX,AL
	RET
;
;**************************************************************************
;  EGALINE
;
;   Write a stream of colors (represented by bytes) to the EGA, with 
;   a translation table for the EGA color map.
;
;   Usage:	 egaline(x,y,colorbuffer,xoff,n)
;			x,y = point to start line at on the screen
;			colorbuffer = 4 byte pointer to stream of 
;			n	bytes.
;			xoff	= offset into the line to be sent to the screen

_EGALINE	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV AL,FLAG  
	OR	AL,AL
	JNZ NOSETUP2
	CALL	SETUPG		; set up the mask regs
	MOV FLAG,1			; set the flag
NOSETUP2:
	MOV AX,[BP+X+6]		; get color table segment
	MOV DS,AX			; use it now

	MOV	AX,0A000H
	MOV ES,AX			; set for addressing
	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 IF POSITIVE
	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:
;	MOV	[BP+X+8],AX		; PUT THE OFFSET BACK
;
	MOV	AX,[BP+X+2]		; get y value 0 < y < 350
	MOV	BX,80
	MUL BX				; multiply by 80 bytes/line
	MOV DI,AX			; put in DI
	MOV AX,[BP+X]		; get x value 0 < x < 640
	MOV BX,AX			; save it
	MOV CL,3
	SHR AX,CL			; divide by 8
	ADD DI,AX			; add it to di = byte offset
;
	MOV CX,BX
	AND CX,0007H		; save only the right three bits
	MOV BL,080H			; here's a bit
	ROR	BL,CL			; move it over some
;
;  At this point, bl has the bit mask for the first bit in the line
;  Keep rotating it and set the mask for each bit to write
;
	MOV CX,[BP+X+10]	; get count of bytes
	CMP	CX,0			; CHECK FOR ZERO BYTES
	JL	LINEDONE		; JUMP TO THE END OF THE ROUTINE
	MOV SI,[BP+X+4]		; where to get the new colors
	ADD	SI,[BP+X+8]		; add in the x offset into the line

	MOV AH,BL			; keep bit rotation in ah
	MOV DX,TRANSSEG		; get segment of transtable
	MOV BX,TRANSOFF		; get offset of transtable
NEXTBIT:
	LODSB				; get the next color to al
	PUSH DS
	MOV DS,DX			; set ds for the transtable
	XLATB				; pick up translated color to al
	PUSH AX				; need it later

	MOV DX,BITMASK		; set the bitmask to current rotation
	MOV AL,AH
	OUT DX,AL			;  send it

	MOV	DX,MAPMASK
	MOV AL,0FH			; open all bit planes
	OUT	DX,AL			; send it

	MOV	AL,ES:[DI]		; latch the whole set of bytes
	MOV BYTE PTR ES:[DI],0H  ; clear all four planes to 0 at this bit
	POP	AX				; get real color back
	OUT	DX,AL			; send it to set the color planes

	MOV DX,DS			;  recover what was in dx
	POP DS
;
	MOV	AL,0FFH			; set all bits
	CMP AH,01			; see if we are at end of byte
	JZ	INCSTORE

NONINC:
	MOV ES:[DI],AL		; write the bit from bitmask
	ROR AH,1			; rotate me
	LOOP	NEXTBIT		; go back for next one
	JMP LINEDONE

INCSTORE:
	STOSB				; place that bit on bit mask and next byte
	ROR AH,1			; rotate me
	LOOP	NEXTBIT

LINEDONE:
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
_EGALINE	ENDP

		
_EGALINE2	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV AL,FLAG  
	OR  AL,AL
	JNZ NO2SETUP2
	CALL	SETUPG		; set up the mask regs
	MOV FLAG,1			; set the flag
NO2SETUP2:
	MOV AX,[BP+X+6]		; get color table segment
	MOV DS,AX			; use it now

	MOV	AX,0A000H
	MOV ES,AX			; set for addressing
	MOV	AX,[BP+X+2]		; get y value 0 < y < 350
	MOV	BX,80
	MUL BX				; multiply by 80 bytes/line
	MOV DI,AX			; put in DI
	MOV AX,[BP+X]		; get x value 0 < x < 640
	MOV BX,AX			; save it
	MOV CL,3
	SHR AX,CL			; divide by 8
	ADD DI,AX			; add it to di = byte offset
;
	MOV CX,BX
	AND CX,0007H		; save only the right three bits
	MOV BL,0C0H			; here's 2 bits
	ROR	BL,CL			; move it over some
;
;  At this point, bl has the bit mask for the first bit in the line
;  Keep rotating it and set the mask for each bit to write
;
	MOV CX,[BP+X+8]		; get count of bytes
	MOV SI,[BP+X+4]		; where to get the new colors

	MOV AH,BL			; keep bit rotation in ah
	MOV DX,[BP+X+12]	; get segment of transtable
	MOV BX,[BP+X+10]	; get offset of transtable

NEXT2BIT:
	LODSB				; get the next color to al
	PUSH DS
	MOV DS,DX			; set ds for the transtable
	XLATB				; pick up translated color to al
	PUSH AX				; need it later

	MOV DX,BITMASK		; set the bitmask to current rotation
	MOV AL,AH
	OUT DX,AL			;  send it

	MOV	DX,MAPMASK
	MOV AL,0FH			; open all bit planes
	OUT	DX,AL			; send it

	MOV	AL,ES:[DI]		; latch the whole set of bytes
	MOV BYTE PTR ES:[DI],0H  ; clear all four planes to 0 at this bit
	POP	AX				; get real color back
	OUT	DX,AL			; send it to set the color planes

	MOV DX,DS			;  recover what was in dx
	POP DS
;
	MOV	AL,0FFH			; set all bits
	CMP AH,03			; see if we are at end of byte
	JZ INC2STORE

NON2INC:
	MOV ES:[DI],AL		; write the bit from bitmask
	ROR AH,1			; rotate me
	ROR AH,1			; rotate me
	LOOP	NEXT2BIT	; go back for next one
	JMP LINE2DONE

INC2STORE:
	STOSB				; place that bit on bit mask and next byte
	ROR AH,1			; rotate me
	ROR AH,1			; again
	LOOP	NEXT2BIT

LINE2DONE:
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
_EGALINE2	ENDP

;**************************************************************************
;  EGALINEA
;
;   Write a stream of colors (represented by bytes) to the EGA, with 
;   a translation table for the EGA color map.  This one includes arbitrary
;   width expansion.
;
;   Usage:	 egalinea(x,y,colorbuffer,n,table,expansion)
;			x,y = point to start line
;			colorbuffer = 4 byte pointer to stream of 
;			n	bytes.
;			table  = 4 byte pointer to translation table, 256 bytes
;					  long for XLAT instruction
;			expansion = how much horizontal pixel expansion you want
;

_EGALINEA	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV AL,FLAG  
	OR  AL,AL
	JNZ NOSETA
	CALL	SETUPG		; set up the mask regs
	MOV FLAG,1			; set the flag
NOSETA:
	MOV AX,[BP+X+6]	 	; get color table segment
	MOV DS,AX			; use it now

	MOV	AX,0A000H
	MOV ES,AX			; set for addressing
	MOV	AX,[BP+X+2]		; get y value 0 < y < 350
	MOV	BX,80
	MUL BX				; multiply by 80 bytes/line
	MOV DI,AX			; put in DI

	MOV AX,[BP+X]		; get x value 0 < x < 640
	MOV BX,AX			;  save it
	MOV CL,3
	SHR AX,CL			; divide by 8
	ADD DI,AX			; add it to di = byte offset
;
	MOV CX,BX
	AND CX,0007H		; save only the right three bits
	MOV BL,080H			; here's a bit
	ROR	BL,CL			; move it over some
;
;  At this point, bl has the bit mask for the first bit in the line
;  Keep rotating it and set the mask for each bit to write
;
	MOV SI,[BP+X+4]	   	; where to get the new colors

	MOV AH,BL			; keep bit rotation in ah
	MOV DX,TRANSSEG		; get segment of transtable
	MOV	BX,TRANSOFF	; get offset of transtable

NEXTBYTE:
	MOV	CX,[BP+X+10]	; pixel expansion number
	LODSB				; the next color to write
	PUSH 	DS
	MOV	DS,DX			; get the seg for xlat from dx
	XLATB				; color translation
	MOV	[BP+X],AL		; used as a local var for translated color

NEXTP:
	MOV	 DX,BITMASK		; set the bitmask to current rotation
	MOV	 AL,AH
	OUT	 DX,AL			;  send it

	MOV	DX,MAPMASK
	MOV	 AL,0FH			; open all bit planes
	OUT	DX,AL			; send it

	MOV	AL,ES:[DI]		; latch the whole set of bytes
	MOV	BYTE PTR ES:[DI],0H  ; clear all four planes to 0 at this bit
	MOV	AL,[BP+X]		; get real color from local var
	OUT	DX,AL			; send it to set the color planes
;
	MOV	AL,0FFH			; set all bits
	MOV	ES:[DI],AL		; set it!
	CMP	 AH,01			; see if we are at end of byte
	JNZ	 SAMEBYTE
	INC		DI			; get us to the next destination byte
SAMEBYTE:
	ROR	 AH,1			; rotate me
	LOOP	NEXTP		; go back for next one

	MOV	DX,DS			; reset xlat segment into dx
	POP	DS				; get data input seg back
	DEC	WORD PTR [BP+X+8] ; number of data points
	JNZ	NEXTBYTE		; do another, if necessary

	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP	BP
	RET
_EGALINEA	ENDP
ifdef QAK
;
;	DRAWS AN INVERTED BOX ON THE EGA SCREEN
;	USAGE:	OUTLINEE(X1,Y1,X2,Y2);
;
_OUTLINEE	PROC	FAR
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES

	MOV	AX,[BP+X+2]			; GET THE FIRST Y VALUE
	CMP	AX,[BP+X+6]			; COMPARE THE SECOND Y VALUE
	JLE	CHECKX				; OK ORDER, CHECK THE X VALUES
	MOV	CX,AX				; SWAP THE Y VALUES
	MOV	AX,[BP+X+6]			;
	MOV	[BP+X+2],AX			;
	MOV	[BP+X+6],CX			;
CHECKX:
	MOV	AX,[BP+X]			; GET THE FIRST X VALUE
	CMP	AX,[BP+X+4]			; COMPARE THE SECOND X VALUE
	JLE	MAKELEN				; OK ORDER, COMPUTE THE LENGTHS
	MOV	CX,AX				; SWAP THE X VALUES
	MOV	AX,[BP+X+4]			;
	MOV	[BP+X],AX			;
	MOV	[BP+X+4],CX			;
MAKELEN:					; COMPUTE THE X AND Y LENGTH OF 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 GET THE LENGTH
	ADD	AX,1				;
	MOV	X_WIDTH,AX			; STORE THE LENGTH IN THE OLD LOCATION FOR THE 2ND VALUE
	MOV	AX,[BP+X+6]			; GET THE LARGER OF THE 2 Y VALUES
	SUB	AX,[BP+X+2]			; SUBTRACT THE SMALLER TO FIND THE LENGTH
	ADD	AX,1				; SUBTRACT FOR THE TOP AND BOTTOM EDGES
	MOV	Y_HEIGHT,AX			; STORE THE Y LENGTH IN THE OLD LOCATION FOR THE 2ND Y VALUE
; SET UP THE REST OF THE PARAMETERS
	MOV	AX,[BP+X]			; THE PIXEL POSITION OF THE LEFT EDGE
	MOV	X_OFF,AX		
	MOV	AX,[BP+X+2]			; THE PIXEL POSITION OF THE TOP LINE
	MOV	Y_OFF,AX
; MAKE THE TOP LINE
	MOV	CX,X_WIDTH			; GET THE NUMBER OF PIXELS TO WRITE
OUTLOOP1:
	PUSH	CX				; SAVE THE COUNT FOR LATER
	MOV	BH,0				; USE THE ZERO GRAPHICS PAGE
	MOV	DX,Y_OFF			; SET THE POSITION OF THE TOP LINE
	MOV	AX,0C8FH			; SET THE PIXEL TO WRITE TO INVERT THE COLOR
	MOV	CX,X_OFF			; GET THE CURRENT X LOCATION
	INC	X_OFF				; MOV THE X LOCATION TO THE NEXT PLACE
	INT	10H					; DO BIOS VIDEO INTERUPT
	POP	CX					; GET COUNT BACK
	LOOP	OUTLOOP1		; GO BACK AND FINISH THE LINE
; MAKE THE MIDDLE LINES
	MOV	AX,[BP+X]			; GET THE LEFT HAND EDGE
	MOV	X_OFF,AX
	MOV	AX,[BP+X+4]			; GET THE RIGHT HAND EDGE
	MOV	X_TEMP,AX
	INC	Y_OFF				; GO TO THE NEXT LINE
	MOV	DX,Y_OFF
	CMP	DX,[BP+X+6]			; CHECK FOR THIS BEING FURTHER THAN THE BOTTOM LINE
	JLE OUTLOOP2			; NOT TO WORRY
	DEC	Y_OFF				; FIX DX BACK TO BE THE LINE
	JMP	ENDLOOP2			; JUMP TO DOING THE BOTTOM LINE
OUTLOOP2:
	CMP	DX,[BP+X+6]			; CHECK FOR THE BOTTOM OF THE OUTLINE DONE
	JE	ENDLOOP2			; IF WE ARE THAN THE BOTTOM EDGE THEN JUMP TO BOTTOM LINE
	MOV	BH,0				; USE THE ZERO GRAPHICS PAGE
	MOV	DX,Y_OFF			; 
	MOV	AX,0C8FH			; SET THE PIXEL TO WRITE TO INVERT THE COLOR
	MOV	CX,X_OFF			; MOVE THE VALUE FOR THE LEFT EDGE
	INT	10H					; DO BIOS VIDEO INTERUPT
	MOV	BH,0				; USE THE ZERO GRAPHICS PAGE
	MOV	DX,Y_OFF			; 
	MOV	AX,0C8FH			; SET THE PIXEL TO WRITE TO INVERT THE COLOR
	MOV	CX,X_TEMP			; MOVE THE VALUE FOR THE RIGHT EDGE
	INT	10H					; DO BIOS VIDEO INTERUPT
	INC	Y_OFF				; GO TO NEXT VERTICAL VALUE
	JMP OUTLOOP2			; GO BACK TO TOP OF THE LOOP

;MAKE THE BOTTOM LINE (Y_OFF IS ALREADY SET TO THE CORRECT VALUE)
ENDLOOP2:
	MOV	CX,X_WIDTH			; GET THE NUMBER OF PIXELS TO WRITE
OUTLOOP3:
	PUSH	CX				; SAVE THE COUNT FOR LATER
	MOV	BH,0				; USE THE ZERO GRAPHICS PAGE
	MOV	DX,Y_OFF			; SET THE POSITION OF THE TOP LINE
	MOV	AX,0C8FH			; SET THE PIXEL TO WRITE TO INVERT THE COLOR
	MOV	CX,X_OFF			; GET THE CURRENT X LOCATION
	INC	X_OFF				; MOV THE X LOCATION TO THE NEXT PLACE
	INT	10H					; DO BIOS VIDEO INTERUPT
	POP	CX					; GET COUNT BACK
	LOOP	OUTLOOP3		; GO BACK AND FINISH THE LINE

DONE:
	POP	ES
	POP	DS
	POP	BP
	RET
_OUTLINEE	ENDP
endif
;
;	DRAWS AN INVERTED BOX ON THE EGA SCREEN
;	USAGE:	INVERSEE(X1,Y1,WIDTH,HEIGHT);
;
_INVERSEE	PROC	FAR
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES

MAKEINV:					; COMPUTE THE X AND Y LENGTH OF THE BOX TO BE INVERTED
	MOV	AX,[BP+X+4]			; GET THE WIDTH
	MOV	X_WIDTH,AX			; STORE THE WIDTH
	MOV	AX,[BP+X+6]			; GET THE HEIGHT
	MOV	Y_HEIGHT,AX			; STORE THE HEIGHT
; SET UP THE REST OF THE PARAMETERS
	MOV	AX,[BP+X+2]			; THE PIXEL POSITION OF THE TOP LINE
	MOV	Y_OFF,AX
	MOV	CX,Y_HEIGHT			; GET THE HEIGHT OF THE BLOCK TO INVERSE
INVTOP1:
	PUSH	CX				; SAVE THE HEIGHT VALUE
	MOV	AX,[BP+X]			; THE PIXEL POSITION OF THE LEFT EDGE
	MOV	X_OFF,AX		
	MOV	CX,X_WIDTH			; GET THE WIDTH OF THE BLOCK TO INVERSE
INVTOP2:
	PUSH	CX				; SAVE THE WIDTH VALUE
	MOV	BH,0				; USE THE ZERO GRAPHICS PAGE
	MOV	DX,Y_OFF			; SET THE POSITION OF THE TOP LINE
	MOV	AX,0C8FH			; SET THE PIXEL TO WRITE TO INVERT THE COLOR
	MOV	CX,X_OFF			; GET THE CURRENT X LOCATION
	INC	X_OFF				; MOV THE X LOCATION TO THE NEXT PLACE
	INT	10H					; DO BIOS VIDEO INTERUPT
	POP	CX					; GET HORIZONTAL COUNT BACK
	LOOP	INVTOP2			; GO BACK AND FINISH THE LINE

	INC	Y_OFF				; INCREMENT THE VERTICAL LINE WE ARE ON
	POP	CX					; GET THE VERTICAL COUNT BACK
	LOOP	INVTOP1			; GO BACK AND FINISH THE BLOCK

DONEINV:
	POP	ES
	POP	DS
	POP	BP
	RET
_INVERSEE	ENDP
;
;	DRAWS A BLOCK ON THE EGA SCREEN
;		USAGE:	egablock(&block,x1,y1,width,height);
;
_EGABLOCK	PROC	FAR
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV	AX,[BP+X+8]			; GET THE WIDTH
	MOV	X_WIDTH,AX			; STORE THE WIDTH
	MOV	AX,[BP+X+10]		; GET THE HEIGHT
	MOV	Y_HEIGHT,AX			; STORE THE HEIGHT
; SET UP THE REST OF THE PARAMETERS
	MOV	AX,[BP+X]			; GET THE OFFSET OF THE ARRAY OF INFORMATION
	MOV	BLKOFF,AX			; SAVE THE OFFSET OF THE ARRAY
	MOV	AX,[BP+X+2]			; GET THE SEGMENT OF THE ARRAY
	MOV	BLKSEG,AX			; SAVE THE SEGMENT
	MOV	AX,[BP+X+6]			; THE PIXEL POSITION OF THE TOP LINE
	MOV	Y_OFF,AX
	MOV	CX,Y_HEIGHT			; GET THE HEIGHT OF THE BLOCK TO COPY
BLKTOP1:
	PUSH	CX				; SAVE THE HEIGHT VALUE
	PUSH	DS
	MOV	AX,[BP+X+4]			; THE PIXEL POSITION OF THE LEFT EDGE
	MOV	X_OFF,AX		
	MOV	CX,X_WIDTH			; GET THE WIDTH OF THE BLOCK TO COPY
BLKTOP2:
	PUSH	CX				; SAVE THE WIDTH VALUE
	MOV	DI,BLKOFF			; GET THE BLOCK OFFSET
	MOV	ES,BLKSEG			; GET THE BLOCK SEGMENT
	MOV	AL,BYTE PTR ES:[DI]	; GET THE VALUE FROM THE BLOCK
	INC	BLKOFF				; GO ON TO THE NEXT LOCATION IN THE BLOCK
	PUSH	DS
	MOV	BX,TRANSOFF			; get offset of transtable
	MOV	DS,TRANSSEG			; get segment of transtable
	XLATB					; pick up translated color
	POP	DS
	MOV	DX,Y_OFF			; SET THE POSITION OF THE TOP LINE
	MOV	AH,0CH				; SET THE PIXEL TO WRITE TO INVERT THE COLOR
	MOV	BH,0				; USE THE ZERO GRAPHICS PAGE
	MOV	CX,X_OFF			; GET THE CURRENT X LOCATION
	INC	X_OFF				; MOV THE X LOCATION TO THE NEXT PLACE
	INT	10H					; DO BIOS VIDEO INTERUPT
	POP	CX					; GET HORIZONTAL COUNT BACK
	LOOP	BLKTOP2			; GO BACK AND FINISH THE LINE

	INC	Y_OFF				; INCREMENT THE VERTICAL LINE WE ARE ON
	POP	DS					; GET THE FIRST DATA SEGMENT BACK
	POP	CX					; GET THE VERTICAL COUNT BACK
	LOOP	BLKTOP1			; GO BACK AND FINISH THE BLOCK

DONEBLK:
	POP		DI
	POP		SI
	POP	ES
	POP	DS
	POP	BP
	RET
_EGABLOCK	ENDP

TESTVAR1	DW	?
TESTVERT	DW	?
TESTCOLOR	DB	?

_SETTRANS	PROC	FAR
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	MOV		TRANSOFF,OFFSET TRANS_TAB	; GET THE OFFSET OF THE TRANSLATION TABLE
	MOV		TRANSSEG,SEG TRANS_TAB	; GET THE SEGMENT OF THE TRANSLATION TABLE

	MOV		DI,TRANSOFF			; GET THE OFFSET OF THE OLD TRANSLATION TABLE
	MOV		ES,TRANSSEG			; GET THE SEGMENT OF THE OLD TRANSLATION TABLE

	LDS		SI,DWORD PTR [BP+X]	; GET THE OFFSET OF THE NEW TRANSLATION TABLE

	MOV		CX,128				; COPY 256 BYTES

	REP		MOVSW				; COPY THE ARRAY

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

ARGX1	EQU WORD PTR [BP+6]
ARGY1	EQU	WORD PTR [BP+8]
ARGX2	EQU	WORD PTR [BP+10]
ARGY2	EQU WORD PTR [BP+12]
ARGN	EQU BYTE PTR [BP+14]

VARVERTINCR	EQU	WORD PTR [BP-6]
VARINCR1	EQU	WORD PTR [BP-8]
VARINCR2	EQU	WORD PTR [BP-10]
VARROUTINE	EQU	WORD PTR [BP-12]

BYTEOFFSETSHIFT	EQU	3
BYTESPERLINE	EQU	80
RMWBITS			EQU 0

_LINE10	PROC	FAR

	PUSH 	BP
	MOV		BP, SP
	SUB 	SP, 16H
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH 	DI

;CONFIGURE THE GRAPHICS CONTROLLER
	MOV		DX, 3CEH
	
	MOV		AH, ARGN
	XOR		AL, AL
	OUT 	DX, AX
	
	MOV 	AX,0F01H

	OUT 	DX, AX
	MOV 	AH, RMWBITS
	MOV 	AL, 3
	OUT 	DX, AX

;CHECK FOR VERTICAL LINE
	MOV		SI, BYTESPERLINE
	
	MOV 	CX, ARGX2
	SUB 	CX, ARGX1
	JZ 		VERTLINE10

;FORCE X1 < X2
	JNS 	L01

	NEG 	CX
	MOV 	BX, ARGX2	
	XCHG	BX, ARGX1
	MOV		ARGX2,BX
	MOV		BX, ARGY2
	XCHG	BX, ARGY1
	MOV		ARGY2,BX	
	
;CALCULATE DY = ABS (Y2-Y1)

L01:	
	MOV 	BX, ARGY2
	SUB		BX, ARGY1
	JZ		HORIZLINE10

	JNS		L03
	
	NEG 	BX
	NEG		SI

;SELECT APPROPRIATE ROUTINE FOR SLOPE OF LINE

L03: 
	MOV 	VARVERTINCR,SI

	MOV		VARROUTINE, OFFSET LOSLOPELINE10
	CMP		BX, CX
	JLE		L04
	MOV		VARROUTINE, OFFSET HISLOPELINE10
	XCHG	BX, CX

;CALCULATE INITIAL DECISION VARIABLE AND INCREMENTS

L04:
	SHL		BX, 1
	MOV		VARINCR1, BX
	SUB		BX, CX
	MOV		SI,BX
	SUB		BX,CX
	MOV		VARINCR2, BX
		
;CALCULATE FIRST PIXEL ADDRESS

	PUSH 	CX
	MOV		AX, ARGY1
	MOV 	BX, ARGX1
	CALL	PIXELADDR10

	MOV		DI, BX
	SHL		AH, CL
	MOV		BL, AH
	MOV 	AL, 8

	POP		CX
	INC		CX
	JMP		VARROUTINE

;ROUTINE FOR VERTICAL LINES

VERTLINE10:
	MOV		AX, ARGY1
	MOV		BX, ARGY2
	MOV		CX, BX
	SUB		CX, AX
	JGE		L31

	NEG		CX
	MOV		AX, BX

L31:	
	INC		CX
	MOV		BX, ARGX1
	PUSH	CX
	CALL	PIXELADDR10
	
;SET UP GRAPHICS CONTROLLER

	SHL		AH, CL
	MOV		AL, 8
	OUT 	DX, AX

	POP 	CX

;DRAW THE LINE
L32:	
	OR		ES:[BX], AL
	ADD 	BX, SI
	LOOP	L32
	
	JMP		LEXIT

;ROUTINE FOR HORIZONTAL LINES (SLOPE=0)

HORIZLINE10:
	PUSH	DS
	MOV		AX, ARGY1
	MOV 	BX, ARGX1
	CALL	PIXELADDR10

	MOV		DI, BX
	MOV		DH, AH
	NOT		DH
	SHL		DH, CL
	NOT 	DH
	MOV		CX, ARGX2
	AND		CL, 7
	XOR 	CL, 7
	MOV		DL, 0FFH
	
	SHL		DL, CL
		
;DETERMINE BYTE OFFSET OF FIRST AND LAST PIXEL IN THE LINE
	
	MOV 	AX, ARGX2
	MOV 	BX, ARGX1

	MOV		CL, BYTEOFFSETSHIFT

	SHR		AX, CL
	SHR		BX, CL
	MOV 	CX, AX
	SUB		CX, BX
	
;GET GRAPHICS CONTROLLER PORT ADDRESS INTO DX

	MOV	 	BX, DX

	MOV 	DX, 3CEH
	MOV 	AL, 8
		
;MAKE VIDEO BUFFER ADDRESSABLE THROUGH DS:SI

	PUSH 	ES
	POP 	DS
	MOV 	SI, DI
	
;SET PIXELS IN LEFTMOST BYTE OF THE LINE

	OR		BH, BH
	JS		L43

	OR 		CX, CX
	JNZ		L42
	
	AND		BL, BH
	JMP		SHORT L44
	
L42:
	MOV		AH, BH
	OUT		DX, AX

	MOVSB
	DEC		CX
	
;USE A FAST 8086 MACHINE INSTRUCTION TO DRAW THE REMAINDER OF THE LINE

L43:	
	MOV		AH, 11111111B
	OUT		DX, AX
	REP		MOVSB

;SET PIXELS IN THE RIGHTMOST BYTE OF THE LINE

L44:	
	MOV		AH, BL
	OUT		DX, AX
	MOVSB
	
	POP 	DS
	JMP		SHORT LEXIT

;ROUTINE FOR DY>=DX (SLOPE<=1)

LOSLOPELINE10:

L10:	
	MOV 	AH, BL
L11:	
	OR 		AH,BL
	ROR		BL, 1
	JC		L14

;BIT MASK NOT SHIFTED OUT

	OR 		SI, SI
	JNS		L12
	ADD		SI, VARINCR1
	LOOP	L11
	OUT 	DX, AX
	OR 		ES:[DI], AL
	JMP		SHORT LEXIT

L12:	
	ADD		SI, VARINCR2
	OUT		DX, AX

	OR		ES:[DI], AL
	
	ADD		DI, VARVERTINCR
	LOOP	L10
	JMP		SHORT LEXIT

;BIT MASK SHIFTED OUT

L14:	
	OUT		DX, AX

	OR		ES:[DI], AL
	INC		DI
	
	OR		SI, SI
	JNS		L15

	ADD 	SI, VARINCR1
	LOOP 	L10
	JMP 	SHORT LEXIT

L15:	
	ADD 	SI, VARINCR2
	ADD		DI, VARVERTINCR
	LOOP	L10
	JMP		SHORT LEXIT

;ROUTINE FOR DY>DX (SLOPE >1)

HISLOPELINE10:
	MOV		BX, VARVERTINCR
L21:	
	OUT 	DX, AX
	OR		ES:[DI], AL
	
	ADD		DI, BX

L22:	
	OR		SI, SI
	JNS		L23
	
	ADD		SI, VARINCR1
	LOOP	L21
	JMP		SHORT LEXIT

L23:	
	ADD		SI, VARINCR2
	ROR		AH, 1
	ADC		DI, 0
	
	LOOP 	L21

;RESTORE DEFAULT GRAPHICS CONTROLLER STATE AND RETURN TO CALLER

LEXIT:	
	XOR		AX, AX
	OUT 	DX, AX
	INC 	AX
	OUT		DX, AX
	MOV 	AL, 3
	OUT		DX, AX
	MOV		AX, 0FF08H
	OUT		DX, AX
	POP 	DI
	POP 	SI
	POP		ES
	POP		DS
	MOV 	SP,BP
	POP 	BP
	RET

_LINE10	ENDP

RMWBITS2	EQU		24

_INVERT10	PROC	FAR

	PUSH 	BP
	MOV		BP, SP
	SUB 	SP, 16H
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH 	DI

;CONFIGURE THE GRAPHICS CONTROLLER
	MOV		DX, 3CEH
	
	MOV		AH, ARGN
	XOR		AL, AL
	OUT 	DX, AX
	
	MOV 	AX,0F01H

	OUT 	DX, AX
	MOV 	AH, RMWBITS2
	MOV 	AL, 3
	OUT 	DX, AX

;CHECK FOR VERTICAL LINE
	MOV		SI, BYTESPERLINE
	
	MOV 	CX, ARGX2
	SUB 	CX, ARGX1
	JZ 		IVERTLINE10

;FORCE X1 < X2
	JNS 	IL01

	NEG 	CX
	MOV 	BX, ARGX2	
	XCHG	BX, ARGX1
	MOV		ARGX2,BX
	MOV		BX, ARGY2
	XCHG	BX, ARGY1
	MOV		ARGY2,BX	
	
;CALCULATE DY = ABS (Y2-Y1)

IL01:	
	MOV 	BX, ARGY2
	SUB		BX, ARGY1
	JZ		IHORIZLINE10

	JNS		IL03
	
	NEG 	BX
	NEG		SI

;SELECT APPROPRIATE ROUTINE FOR SLOPE OF LINE

IL03: 
	MOV 	VARVERTINCR,SI

	MOV		VARROUTINE, OFFSET ILOSLOPELINE10
	CMP		BX, CX
	JLE		IL04
	MOV		VARROUTINE, OFFSET IHISLOPELINE10
	XCHG	BX, CX

;CALCULATE INITIAL DECISION VARIABLE AND INCREMENTS

IL04:
	SHL		BX, 1
	MOV		VARINCR1, BX
	SUB		BX, CX
	MOV		SI,BX
	SUB		BX,CX
	MOV		VARINCR2, BX
		
;CALCULATE FIRST PIXEL ADDRESS

	PUSH 	CX
	MOV		AX, ARGY1
	MOV 	BX, ARGX1
	CALL	PIXELADDR10

	MOV		DI, BX
	SHL		AH, CL
	MOV		BL, AH
	MOV 	AL, 8

	POP		CX
	INC		CX
	JMP		VARROUTINE

;ROUTINE FOR VERTICAL LINES

IVERTLINE10:
	MOV		AX, ARGY1
	MOV		BX, ARGY2
	MOV		CX, BX
	SUB		CX, AX
	JGE		IL31

	NEG		CX
	MOV		AX, BX

IL31:	
	INC		CX
	MOV		BX, ARGX1
	PUSH	CX
	CALL	PIXELADDR10
	
;SET UP GRAPHICS CONTROLLER

	SHL		AH, CL
	MOV		AL, 8
	OUT 	DX, AX

	POP 	CX

;DRAW THE LINE
IL32:	
	OR		ES:[BX], AL
	ADD 	BX, SI
	LOOP	IL32
	
	JMP		ILEXIT

;ROUTINE FOR HORIZONTAL LINES (SLOPE=0)

IHORIZLINE10:
	PUSH	DS
	MOV		AX, ARGY1
	MOV 	BX, ARGX1
	CALL	PIXELADDR10

	MOV		DI, BX
	MOV		DH, AH
	NOT		DH
	SHL		DH, CL
	NOT 	DH
	MOV		CX, ARGX2
	AND		CL, 7
	XOR 	CL, 7
	MOV		DL, 0FFH
	
	SHL		DL, CL
		
;DETERMINE BYTE OFFSET OF FIRST AND LAST PIXEL IN THE LINE
	
	MOV 	AX, ARGX2
	MOV 	BX, ARGX1

	MOV		CL, BYTEOFFSETSHIFT

	SHR		AX, CL
	SHR		BX, CL
	MOV 	CX, AX
	SUB		CX, BX
	
;GET GRAPHICS CONTROLLER PORT ADDRESS INTO DX

	MOV	 	BX, DX

	MOV 	DX, 3CEH
	MOV 	AL, 8
		
;MAKE VIDEO BUFFER ADDRESSABLE THROUGH DS:SI

	PUSH 	ES
	POP 	DS
	MOV 	SI, DI
	
;SET PIXELS IN LEFTMOST BYTE OF THE LINE

	OR		BH, BH
	JS		IL43

	OR 		CX, CX
	JNZ		IL42
	
	AND		BL, BH
	JMP		SHORT IL44
	
IL42:
	MOV		AH, BH
	OUT		DX, AX

	MOVSB
	DEC		CX
	
;USE A FAST 8086 MACHINE INSTRUCTION TO DRAW THE REMAINDER OF THE LINE

IL43:	
	MOV		AH, 11111111B
	OUT		DX, AX
	REP		MOVSB

;SET PIXELS IN THE RIGHTMOST BYTE OF THE LINE

IL44:	
	MOV		AH, BL
	OUT		DX, AX
	MOVSB
	
	POP 	DS
	JMP		SHORT ILEXIT

;ROUTINE FOR DY>=DX (SLOPE<=1)

ILOSLOPELINE10:

IL10:	
	MOV 	AH, BL
IL11:	
	OR 		AH,BL
	ROR		BL, 1
	JC		IL14

;BIT MASK NOT SHIFTED OUT

	OR 		SI, SI
	JNS		IL12
	ADD		SI, VARINCR1
	LOOP	IL11
	OUT 	DX, AX
	OR 		ES:[DI], AL
	JMP		SHORT ILEXIT

IL12:	
	ADD		SI, VARINCR2
	OUT		DX, AX

	OR		ES:[DI], AL
	
	ADD		DI, VARVERTINCR
	LOOP	IL10
	JMP		SHORT ILEXIT

;BIT MASK SHIFTED OUT

IL14:	
	OUT		DX, AX

	OR		ES:[DI], AL
	INC		DI
	
	OR		SI, SI
	JNS		IL15

	ADD 	SI, VARINCR1
	LOOP 	IL10
	JMP 	SHORT ILEXIT

IL15:	
	ADD 	SI, VARINCR2
	ADD		DI, VARVERTINCR
	LOOP	IL10
	JMP		SHORT ILEXIT

;ROUTINE FOR DY>DX (SLOPE >1)

IHISLOPELINE10:
	MOV		BX, VARVERTINCR
IL21:	
	OUT 	DX, AX
	OR		ES:[DI], AL
	
	ADD		DI, BX

IIL23:	
	OR		SI, SI
	JNS		IL23
	
	ADD		SI, VARINCR1
	LOOP	IL21
	JMP		SHORT ILEXIT

IL23:	
	ADD		SI, VARINCR2
	ROR		AH, 1
	ADC		DI, 0
	
	LOOP 	IL21

;RESTORE DEFAULT GRAPHICS CONTROLLER STATE AND RETURN TO CALLER

ILEXIT:	
	XOR		AX, AX
	OUT 	DX, AX
	INC 	AX
	OUT		DX, AX
	MOV 	AL, 3
	OUT		DX, AX
	MOV		AX, 0FF08H
	OUT		DX, AX
	POP 	DI
	POP 	SI
	POP		ES
	POP		DS
	MOV 	SP,BP
	POP 	BP
	RET

_INVERT10	ENDP

;NAME:	ELLIPSE10
;
ARGXC	EQU WORD PTR [BP+6]
ARGYC	EQU WORD PTR [BP+8]
ARGA	EQU WORD PTR [BP+10]
ARGB	EQU WORD PTR [BP+12]
ARGN	EQU	BYTE PTR [BP+14]

ULADDR	EQU WORD PTR [BP-6]
URADDR	EQU WORD PTR [BP-8]
LLADDR	EQU WORD PTR [BP-10]
LRADDR	EQU WORD PTR [BP-12]
LMASK	EQU BYTE PTR [BP-14]
RMASK	EQU BYTE PTR [BP-16]


VARD		EQU WORD PTR [BP-20]
VARDX		EQU WORD PTR [BP-24]
VARDY		EQU WORD PTR [BP-28]
ASQUARED	EQU WORD PTR [BP-32]
BSQUARED	EQU WORD PTR [BP-36]
TWOASQUARED	EQU WORD PTR [BP-40]
TWOBSQUARED	EQU WORD PTR [BP-44]

RMWBITS		EQU	00H
BYTESPERLINE EQU	80

_CIRCLE10	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	SUB	SP,50
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI
	
;SET GRAPHICS CONTROLLER MODE REGISTER
	MOV	DX,3CEH
	MOV	AX,0005H
	OUT	DX,AX

;SET DATA ROTATE/FUNCTION SELECT REGISTER
	MOV	AH,RMWBITS
	MOV	AL,3
	OUT DX,AX

;SET SET/RESET AND ENABLE SET/RESET REGISTERS
	MOV AH,ARGN
	MOV	AL,0
	OUT DX,AX
	MOV	AX,0F01H
	OUT DX,AX

;INITIAL CONSTANTS
	MOV AX,ARGA
	MUL	AX
	MOV ASQUARED,AX
	MOV	ASQUARED+2,DX
	SHL	AX,1
	RCL	DX,1
	MOV	TWOASQUARED,AX
	MOV	TWOASQUARED+2,DX
	MOV	AX,ARGB
	MUL	AX
	MOV BSQUARED,AX
	MOV BSQUARED+2,DX
	SHL	AX,1
	RCL DX,1
	MOV TWOBSQUARED,AX
	MOV TWOBSQUARED+2,DX

;PLOT PIXELS FROM (0,B) UNTIL DY/DX =-1
;INITIAL BUFFER ADDRESS AND BIT MASK
	MOV	AX,BYTESPERLINE
	MUL	ARGB
	MOV	SI,AX
	MOV	DI,AX
	MOV	AX,ARGYC
	MOV	BX,ARGXC
	CALL	PIXELADDR10

	MOV	AH,1
	SHL	AH,CL
	MOV LMASK,AH
	MOV RMASK,AH
	
	ADD	SI,BX
	MOV	ULADDR,SI
	MOV URADDR,SI
	SUB	BX,DI
	MOV	LLADDR,BX
	MOV	LRADDR,BX

;INITIAL DECISION VARIABLES
	XOR	AX,AX
	MOV	VARDX,AX
	MOV	VARDX+2,AX

	MOV	AX,TWOASQUARED
	MOV DX,TWOASQUARED+2
	MOV CX,ARGB
	CALL LONGMULTIPLY
	MOV VARDY,AX
	MOV VARDY+2,DX

	MOV AX,ASQUARED
	MOV	DX,ASQUARED+2
	SAR DX,1
	RCR	AX,1
	SAR	DX,1
	RCR AX,1

	ADD AX,BSQUARED
	ADC	DX,BSQUARED+2
	MOV	VARD,AX
	MOV VARD+2,DX

	MOV	AX,ASQUARED
	MOV	DX,ASQUARED+2
	MOV CX,ARGB
	CALL LONGMULTIPLY
	SUB	VARD,AX
	SBB	VARD+2,DX
	
	;LOOP UNTIL DY/DX>=-1
	MOV	BX,ARGB
	XOR	CX,CX
	
C10:	
	MOV	AX,VARDX
	MOV	DX,VARDX+2
	SUB	AX,VARDY
	SBB	DX,VARDY+2
	JNS	C20
	
	CALL	SET4PIXELS
	MOV CX,1
	CMP	VARD+2,0
	JS	C11
	MOV	CH,1
	DEC	BX
	
	MOV AX,VARDY
	MOV	DX,VARDY+2
	SUB AX,TWOASQUARED
	SBB	DX,TWOASQUARED+2
	MOV VARDY,AX
	MOV	VARDY+2,DX

	SUB	VARD,AX
	SBB	VARD+2,DX
	
C11:
	MOV AX,VARDX
	MOV DX,VARDX+2
	ADD	AX,TWOBSQUARED
	ADC	DX,TWOBSQUARED+2
	MOV VARDX,AX
	MOV VARDX+2,DX
	ADD	AX,BSQUARED
	ADC	DX,BSQUARED+2
	ADD VARD,AX
	ADC	VARD+2,DX
	JMP	C10
	
;PLOT PIXELS FROM CURRENT (X,Y) UNTIL Y<0
	
C20:
	PUSH	BX
	PUSH	CX
	MOV	AX,ASQUARED
	MOV	DX,ASQUARED+2
	SUB	AX,BSQUARED
	SBB	DX,BSQUARED+2
	MOV BX,AX
	MOV CX,DX
	
	SAR DX,1
	RCR	AX,1
	ADD AX,BX
	ADC	DX,CX
	
	SUB AX,VARDX
	SBB	DX,VARDX+2
	SUB	AX,VARDY
	SBB	DX,VARDY+2
	
	SAR	DX,1
	RCR	AX,1
	
	ADD	VARD,AX
	ADC	VARD+2,DX
	
;LOOP UNTIL Y<0
	POP CX
	POP BX
C21:
	CALL SET4PIXELS
	MOV CX,100H
	
	CMP	VARD+2,0
	JNS	C22
	
	MOV CL,1
	MOV AX,VARDX
	MOV DX,VARDX+2
	ADD AX,TWOBSQUARED
	ADC	DX,TWOBSQUARED+2
	MOV	VARDX,AX
	MOV	VARDX+2,DX
	
	ADD	VARD,AX
	ADC	VARD+2,DX
	
C22:	
	MOV AX,VARDY
	MOV	DX,VARDY+2
	SUB	AX,TWOASQUARED
	SBB	DX,TWOASQUARED+2
	MOV	VARDY,AX
	MOV	VARDY+2,DX

	SUB	AX,ASQUARED
	SBB	DX,ASQUARED+2
	SUB	VARD,AX
	SBB	VARD+2,DX
	
	DEC	BX
	JNS	C21
	
;RESTORE DEFAULT GRAPHICS CONTROLLER REGISTERS
CEXIT:
	MOV	AX,0FF08H
	MOV	DX,3CEH
	OUT	DX,AX
	MOV	AX,0003
	OUT	DX,AX
	MOV AX,0001
	OUT DX,AX
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	MOV SP,BP
	POP	BP
	RET
	
_CIRCLE10	ENDP

;NAME:	INCIRC10
;
ARGXC	EQU WORD PTR [BP+6]
ARGYC	EQU WORD PTR [BP+8]
ARGA	EQU WORD PTR [BP+10]
ARGB	EQU WORD PTR [BP+12]

ULADDR	EQU WORD PTR [BP-6]
URADDR	EQU WORD PTR [BP-8]
LLADDR	EQU WORD PTR [BP-10]
LRADDR	EQU WORD PTR [BP-12]
LMASK	EQU BYTE PTR [BP-14]
RMASK	EQU BYTE PTR [BP-16]


VARD		EQU WORD PTR [BP-20]
VARDX		EQU WORD PTR [BP-24]
VARDY		EQU WORD PTR [BP-28]
ASQUARED	EQU WORD PTR [BP-32]
BSQUARED	EQU WORD PTR [BP-36]
TWOASQUARED	EQU WORD PTR [BP-40]
TWOBSQUARED	EQU WORD PTR [BP-44]

RMWBITS2	EQU	24
BYTESPERLINE EQU	80

_INCIRC10	PROC	FAR
	PUSH	BP
	MOV	BP,SP
	SUB	SP,50
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI
	
;SET GRAPHICS CONTROLLER MODE REGISTER
	MOV	DX,3CEH
	MOV	AX,0005H
	OUT	DX,AX

;SET DATA ROTATE/FUNCTION SELECT REGISTER
	MOV	AH,RMWBITS2
	MOV	AL,3
	OUT DX,AX

;SET SET/RESET AND ENABLE SET/RESET REGISTERS
	MOV AH,0				; ARGN
	MOV	AL,0
	OUT DX,AX
	MOV	AX,0F01H
	OUT DX,AX

;INITIAL CONSTANTS
	MOV AX,ARGA
	MUL	AX
	MOV ASQUARED,AX
	MOV	ASQUARED+2,DX
	SHL	AX,1
	RCL	DX,1
	MOV	TWOASQUARED,AX
	MOV	TWOASQUARED+2,DX
	MOV	AX,ARGB
	MUL	AX
	MOV BSQUARED,AX
	MOV BSQUARED+2,DX
	SHL	AX,1
	RCL DX,1
	MOV TWOBSQUARED,AX
	MOV TWOBSQUARED+2,DX

;PLOT PIXELS FROM (0,B) UNTIL DY/DX =-1
;INITIAL BUFFER ADDRESS AND BIT MASK
	MOV	AX,BYTESPERLINE
	MUL	ARGB
	MOV	SI,AX
	MOV	DI,AX
	MOV	AX,ARGYC
	MOV	BX,ARGXC
	CALL	PIXELADDR10

	MOV	AH,1
	SHL	AH,CL
	MOV LMASK,AH
	MOV RMASK,AH
	
	ADD	SI,BX
	MOV	ULADDR,SI
	MOV URADDR,SI
	SUB	BX,DI
	MOV	LLADDR,BX
	MOV	LRADDR,BX

;INITIAL DECISION VARIABLES
	XOR	AX,AX
	MOV	VARDX,AX
	MOV	VARDX+2,AX

	MOV	AX,TWOASQUARED
	MOV DX,TWOASQUARED+2
	MOV CX,ARGB
	CALL LONGMULTIPLY
	MOV VARDY,AX
	MOV VARDY+2,DX

	MOV AX,ASQUARED
	MOV	DX,ASQUARED+2
	SAR DX,1
	RCR	AX,1
	SAR	DX,1
	RCR AX,1

	ADD AX,BSQUARED
	ADC	DX,BSQUARED+2
	MOV	VARD,AX
	MOV VARD+2,DX

	MOV	AX,ASQUARED
	MOV	DX,ASQUARED+2
	MOV CX,ARGB
	CALL LONGMULTIPLY
	SUB	VARD,AX
	SBB	VARD+2,DX
	
	;LOOP UNTIL DY/DX>=-1
	MOV	BX,ARGB
	XOR	CX,CX
	
IC10:	
	MOV	AX,VARDX
	MOV	DX,VARDX+2
	SUB	AX,VARDY
	SBB	DX,VARDY+2
	JNS	IC20
	
	CALL	SET4PIXELS
	MOV CX,1
	CMP	VARD+2,0
	JS	IC11
	MOV	CH,1
	DEC	BX
	
	MOV AX,VARDY
	MOV	DX,VARDY+2
	SUB AX,TWOASQUARED
	SBB	DX,TWOASQUARED+2
	MOV VARDY,AX
	MOV	VARDY+2,DX

	SUB	VARD,AX
	SBB	VARD+2,DX
	
IC11:
	MOV AX,VARDX
	MOV DX,VARDX+2
	ADD	AX,TWOBSQUARED
	ADC	DX,TWOBSQUARED+2
	MOV VARDX,AX
	MOV VARDX+2,DX
	ADD	AX,BSQUARED
	ADC	DX,BSQUARED+2
	ADD VARD,AX
	ADC	VARD+2,DX
	JMP	IC10
	
;PLOT PIXELS FROM CURRENT (X,Y) UNTIL Y<0
	
IC20:
	PUSH	BX
	PUSH	CX
	MOV	AX,ASQUARED
	MOV	DX,ASQUARED+2
	SUB	AX,BSQUARED
	SBB	DX,BSQUARED+2
	MOV BX,AX
	MOV CX,DX
	
	SAR DX,1
	RCR	AX,1
	ADD AX,BX
	ADC	DX,CX
	
	SUB AX,VARDX
	SBB	DX,VARDX+2
	SUB	AX,VARDY
	SBB	DX,VARDY+2
	
	SAR	DX,1
	RCR	AX,1
	
	ADD	VARD,AX
	ADC	VARD+2,DX
	
;LOOP UNTIL Y<0
	POP CX
	POP BX
IC21:
	CALL SET4PIXELS
	MOV CX,100H
	
	CMP	VARD+2,0
	JNS	IC22
	
	MOV CL,1
	MOV AX,VARDX
	MOV DX,VARDX+2
	ADD AX,TWOBSQUARED
	ADC	DX,TWOBSQUARED+2
	MOV	VARDX,AX
	MOV	VARDX+2,DX
	
	ADD	VARD,AX
	ADC	VARD+2,DX
	
IC22:	
	MOV AX,VARDY
	MOV	DX,VARDY+2
	SUB	AX,TWOASQUARED
	SBB	DX,TWOASQUARED+2
	MOV	VARDY,AX
	MOV	VARDY+2,DX

	SUB	AX,ASQUARED
	SBB	DX,ASQUARED+2
	SUB	VARD,AX
	SBB	VARD+2,DX
	
	DEC	BX
	JNS	IC21
	
;RESTORE DEFAULT GRAPHICS CONTROLLER REGISTERS
ICEXIT:
	MOV	AX,0FF08H
	MOV	DX,3CEH
	OUT	DX,AX
	MOV	AX,0003
	OUT	DX,AX
	MOV AX,0001
	OUT DX,AX
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	MOV SP,BP
	POP	BP
	RET
_INCIRC10	ENDP

SET4PIXELS	PROC	NEAR
	PUSH	AX
	PUSH	BX
	PUSH	DX
	MOV DX,3CEH
	XOR	BX,BX
	TEST	CH,CH
	JZ	C30
	MOV	BX,BYTESPERLINE
	NEG	BX
C30:
	MOV	AL,8
	
;PIXELS AR (XC-X,YC+Y) AND XC-C,YC-Y)

	XOR	SI,SI
	MOV	AH,LMASK
	ROL	AH,CL
	RCL	SI,1
	NEG	SI
	MOV DI,SI
	ADD	SI,ULADDR
	ADD	SI,BX
	ADD	DI,LLADDR
	SUB	DI,BX
	MOV	LMASK,AH
	MOV	ULADDR,SI
	MOV	LLADDR,DI
	OUT	DX,AX
	MOV	CH,ES:[SI]
	MOV	ES:[SI],CH
	MOV	CH,ES:[DI]
	MOV	ES:[DI],CH
	
;PIXELS AT (XC+X,YC+Y) AND (XC+X,YC+Y)

	XOR	SI,SI
	MOV	AH,RMASK
	ROR	AH,CL
	RCL	SI,1
	MOV	DI,SI
	
	ADD	SI,URADDR
	ADD SI,BX
	ADD	DI,LRADDR
	SUB	DI,BX
	
	MOV	RMASK,AH
	MOV	URADDR,SI
	MOV	LRADDR,DI
	
	OUT	DX,AX
	MOV	CH,ES:[SI]
	MOV	ES:[SI],CH
	MOV	CH,ES:[DI]
	MOV ES:[DI],CH
	
	POP	DX
	POP BX
	POP AX
	RET

SET4PIXELS	ENDP

LONGMULTIPLY	PROC	NEAR

	PUSH	AX
	MOV	AX,DX
	MUL	CX
	XCHG	AX,CX
	POP DX
	MUL DX
	ADD	DX,CX
	RET

LONGMULTIPLY	ENDP


		ENDPS
		END
