;EASE$$$ READ ONLY COPY of file ÒRGNBLT.m.aÓ
; 1.1	CCH 11/11/1988 Fixed Header.
; 1.0	CCH 11/ 9/1988 Adding to EASE.
; OLD REVISIONS BELOW
; 1.2	CCH 10/12/1988 Changed Òm.GrafType.aÓ to ÒGrafType.m.aÓ.
; 1.1	MSH 5/18/88 Changed inclides to use m.GRAPHTYPES to work under EASE.
; 1.0	BBM 2/11/88 Adding file for the first time into EASEÉ
; END EASE MODIFICATION HISTORY 


		BLANKS	ON
		STRING	ASIS

		INCLUDE  'GRAFTYPES.m.a'
;------------------------------------------------------------------
;
;  -->	RGNBLT.TEXT
;
;  Low level block transfer clipped to an arbitrary region.
;


RgnBlt	PROC  EXPORT
		IMPORT BitBlt,RSect,ShieldCursor,ShowCursor
		IMPORT SeekRgn,PatExpand,ColorMap,InitRgn,TrimRect
;--------------------------------------------------------------
;
;  PROCEDURE RgnBlt(srcBits,dstBits: BitMap;
;			srcRect,dstRect: Rect;
;			mode: INTEGER; pat: Pattern;
;			rgnA,rgnB,rgnC: RgnHandle);
;
;  TRANSFERS A RECTANGULAR BLOCK OF BITS CLIPPED TO THE DESTINATION
;  BITMAP'S BOUNDS AND TO THE INTERSECTION OF THREE REGIONS.
;  MODE SPECIFIES THE TRANSFER MODE AND WHETHER THE SOURCE SHOULD COME
;  FROM THE SOURCE BITMAP OR FROM A REPEATING PATTERN.
;
;  COPYRIGHT APPLE COMPUTER INC.
;  DESIGNED AND WRITTEN BY BILL ATKINSON
;
;  THIS CODE IS POSITION INDEPENDENT, RE-ENTRANT, AND READ-ONLY.
;  CLOBBERS ONLY A0.
;
;  MODES:	   0 SRC		 --> DST
;		   1 SRC OR  DST --> DST
;		   2 SRC XOR DST --> DST
;		   3 SRC BIC DST --> DST
;
;		   4 (NOT SRC)	   --> DST
;		   5 (NOT SRC) OR  DST --> DST
;		   6 (NOT SRC) XOR DST --> DST
;		   7 (NOT SRC) BIC DST --> DST
;
;		   8 PATTERN	 --> DST
;		   9 PATTERN OR  DST --> DST
;		  10 PATTERN XOR DST --> DST
;		  11 PATTERN BIC DST --> DST
;
;		  12 (NOT PATTERN)		   --> DST
;		  13 (NOT PATTERN) OR  DST --> DST
;		  14 (NOT PATTERN) XOR DST --> DST
;		  15 (NOT PATTERN) BIC DST --> DST
;
;


;----------------------------------------------------
;
;  A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE		EQU 	34				;SIZE OF PARAMETERS
SRCBITS 		EQU 	PARAMSIZE+8-4			;LONG, ADDR OF BITMAP
DSTBITS 		EQU 	SRCBITS-4			;LONG, ADDR OF BITMAP
SRCRECT 		EQU 	DSTBITS-4			;LONG, ADDR OF RECT
DSTRECT 		EQU 	SRCRECT-4			;LONG, ADDR OF RECT
MODE			EQU 	DSTRECT-2			;WORD
PAT 		EQU 	MODE-4				;LONG, ADDR OF PATTERN
RGNA			EQU 	PAT-4				;LONG, RGNHANDLE
RGNB			EQU 	RGNA-4				;LONG, RGNHANDLE
RGNC			EQU 	RGNB-4				;LONG, RGNHANDLE


;-------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
EXPAT			EQU 	-64 			;16 LONGS
MINRECT 		EQU 	EXPAT-8 			;RECT
STATEA			EQU 	MINRECT-RGNREC			;RGN STATE RECORD
STATEB			EQU 	STATEA-RGNREC			;RGN STATE RECORD
STATEC			EQU 	STATEB-RGNREC			;RGN STATE RECORD
SAVESTK 		EQU 	STATEC-4			;LONG
RECTFLAG		EQU 	SAVESTK-2			;WORD
MASKBUF 		EQU 	RECTFLAG-4			;LONG
BUFLEFT 		EQU 	MASKBUF-2			;WORD
BUFSIZE 		EQU 	BUFLEFT-2			;WORD
SRCADDR 		EQU 	BUFSIZE-4			;LONG
DSTADDR 		EQU 	SRCADDR-4			;LONG
SRCROW			EQU 	DSTADDR-4			;LONG
DSTROW			EQU 	SRCROW-4			;LONG
VERT			EQU 	DSTROW-2			;WORD
MODECASE		EQU 	VERT-4				;LONG
SAVEA5			EQU 	MODECASE-4			;LONG
FIRSTV			EQU 	SAVEA5-2			;WORD
LASTV			EQU 	FIRSTV-2			;WORD
VBUMP			EQU 	LASTV-2 			;WORD, MUST BE ABOVE HBUMP
HBUMP			EQU 	VBUMP-2 			;WORD
SRCRECT2		EQU 	HBUMP-8 			;RECT
MASKADDR		EQU 	SRCRECT2-4			;LONG
VARSIZE 		EQU 	MASKADDR			;SIZE OF LOCAL VARIABLES



		LINK	A6,#VARSIZE 			;ALLOCATE LOCAL VARIABLES
		MOVEM.L D0-D7/A2-A5,-(SP)			;SAVE REGS
		MOVE.L	SP,SAVESTK(A6)				;REMEMBER STACK FOR LATER
		MOVE.L	A5,SAVEA5(A6)				;REMEMBER GLOBAL PTR


;----------------------------------------------------------------
;
;  ADJUST MODE AND PATTERN IF COLOR FILTERING.
;
		MOVE	MODE(A6),-(SP)				;YES, PUSH INPUT MODE
		MOVE.L	PAT(A6),-(SP)				;PUSH ADDR OF INPUT PATTERN
		JSR 	COLORMAP				;ALTER BY THECOLOR, THEFILTER
		MOVE.L	(SP)+,PAT(A6)				;GET (ALTERED) PATTERN
		MOVE	(SP)+,MODE(A6)				;GET (ALTERED) MODE


;------------------------------------------------------
;
;  GET THREE REGION HANDLES AND DE-REFERENCE THEM.
;
		MOVE.L	RGNA(A6),A1 			;GET RGNHANDLE
		MOVE.L	(A1),A1 				;DE-REFERENCE IT
		MOVE.L	RGNB(A6),A2 			;GET RGNHANDLE
		MOVE.L	(A2),A2 				;DE-REFERENCE IT
		MOVE.L	RGNC(A6),A3 			;GET RGNHANDLE
		MOVE.L	(A3),A3 				;DE-REFERENCE IT


;-------------------------------------------------------------------
;
;  CALC MINRECT, THE INTERSECTION OF DSTRECT, DSTBITS.BOUNDS,
;  AND 3 REGION BOUNDING BOXES.  QUIT IF THE INTERSECTION IS EMPTY.
;
		MOVE.L	DSTRECT(A6),-(SP)			;PUSH DSTRECT
		MOVE.L	DSTBITS(A6),A4				;A4 POINTS TO DSTBITS
		PEA 	BOUNDS(A4)				;PUSH DSTBITS.BOUNDS
		PEA 	RGNBBOX(A1) 			;PUSH RGNA BBOX
		PEA 	RGNBBOX(A2) 			;PUSH RGNB BBOX
		PEA 	RGNBBOX(A3) 			;PUSH RGNC BBOX
		MOVE	#5,-(SP)				;PUSH NRECTS=5
		PEA 	MINRECT(A6) 			;PUSH WHERE TO PUT RESULT
		JSR 	RSECT					;CALC INTERSECTION
		BEQ 	GOHOME					;QUIT IF EMPTY


;----------------------------------------------------
;
;  HIDE THE CURSOR IF IT INTERSECTS MINRECT
;
		PEA 	MINRECT(A6) 			;PUSH SHIELD RECT
		MOVE.L	BOUNDS+TOPLEFT(A4),-(SP)		;PUSH DELTA TO CONVERT TO GLOBAL
		JSR 	SHIELDCURSOR				;REMOVE CURSOR IF INTERSECT


;----------------------------------------------------
;
;  ARE ALL THREE REGIONS RECTANGULAR ?
;
		CMP 	#10,RGNSIZE(A1) 			;IS RGNA RECTANGULAR ?
		BNE.S	NOTRECT 				;NO, CONTINUE
		CMP 	#10,RGNSIZE(A3) 			;IS RGN3 RECTANGULAR ?
		BNE.S	NOTRECT 				;NO, CONTINUE
		CMP 	#10,RGNSIZE(A2) 			;IS RGN2 RECTANGULAR ?
		BEQ.S	OKRECT					;NO, CONTINUE
;
;  If only rgnB (visRgn) is non-rectangular, then check if
;  its intersection with minrect would be rectangular.
;  IF TrimRect(rgnB,minRect) then take the fast way.
;
		MOVE.L	RGNB(A6),-(SP)				;push rgnHandle
		PEA 	minRect(A6) 			;push addr of minRect
		JSR 	TrimRect				;call trimRect
		BLT 	DONE					;quit if intersection empty
		BGT.S	NOTRECT 				;continue if non-rectangular

;--------------------------------------------------------------
;
;  SINCE ALL THREE REGIONS ARE RECTANGULAR, WE WILL USE BITBLT.
;  FIRST CLIP SRCRECT TO MATCH MINRECT.  (COPY SRCRECT SINCE IT'S NOT VAR)
;
OKRECT	MOVE.L	SRCRECT(A6),A2				;POINT TO SRC RECT
		LEA 	SRCRECT2(A6),A0 			;POINT TO LOCAL COPY OF SRCRECT
		MOVE.L	DSTRECT(A6),A3				;POINT TO DSTRECT

		MOVE	MINRECT+TOP(A6),D0			;GET MINRECT TOP
		SUB 	TOP(A3),D0				;CONVERT FROM DST COORDS
		ADD 	TOP(A2),D0				;TO SRC COORDS
		MOVE	D0,TOP(A0)				;PUT CLIPPED SRC TOP INTO COPY

		MOVE	MINRECT+LEFT(A6),D0 		;GET MINRECT LEFT
		SUB 	LEFT(A3),D0 			;CONVERT FROM DST COORDS
		ADD 	LEFT(A2),D0 			;TO SRC COORDS
		MOVE	D0,LEFT(A0) 			;PUT CLIPPED SRC LEFT INTO COPY


;----------------------------------------------------
;
;  PUSH PARAMETERS AND CALL BITBLT
;
		MOVE.L	SRCBITS(A6),-(SP)			;PUSH SRCBITS
		MOVE.L	A4,-(SP)				;PUSH DSTBITS
		MOVE.L	A0,-(SP)				;PUSH SRCRECT COPY
		PEA 	MINRECT(A6) 			;PUSH DST = MINRECT
		MOVE	MODE(A6),-(SP)				;PUSH MODE
		MOVE.L	PAT(A6),-(SP)				;PUSH PATTERN
		JSR 	BITBLT					;CALL BITBLT
		BRA 	DONE					;RESTORE CURSOR AND QUIT


;-----------------------------------
;
;  CALC BUFLEFT AND BUFSIZE
;
NOTRECT MOVE	MINRECT+LEFT(A6),D1 		;GET MINRECT LEFT
		SUB 	BOUNDS+LEFT(A4),D1			;CONVERT TO GLOBAL COORDS
		AND 	#$FFF0,D1				;TRUNC TO MULT OF 16
		ADD 	BOUNDS+LEFT(A4),D1			;CONVERT BACK TO LOCAL
		MOVE	D1,BUFLEFT(A6)				;SAVE AS BUFLEFT
		MOVE	MINRECT+RIGHT(A6),D0			;GET MINRECT RIGHT
		SUB 	D1,D0					;CALC WIDTH IN DOTS
		LSR 	#5,D0					;DIV BY 32 FOR LONGS
		MOVE	D0,BUFSIZE(A6)				;BUFSIZE = # LONGS -1


;-----------------------------------------------------------------------
;
;  ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK.
;
CLRMASK CLR.L	-(SP)					;ALLOCATE AND CLEAR
		DBRA	D0,CLRMASK				;LOOP TILL DONE
		MOVE.L	SP,MASKBUF(A6); 			;REMEMBER WHERE MASKBUF IS


;-------------------------------------------------------------------
;
;  INIT STATE RECORDS VERT0 AND VERT1 IN CASE RECTANGULAR
;
		MOVE	#32767,D0
		MOVE	D0,STATEA+NEXTV(A6)
		MOVE	D0,STATEB+NEXTV(A6)
		MOVE	D0,STATEC+NEXTV(A6)
		NEG 	D0
		MOVE	D0,STATEA+THISV(A6)
		MOVE	D0,STATEB+THISV(A6)
		MOVE	D0,STATEC+THISV(A6)


;----------------------------------------------------------------------
;
;  ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
;
		CLR 	D5					;INIT ALL RGNS RECT
		MOVE.L	RGNA(A6),A0 			;GET RGNHANDLE
		MOVE.L	(A0),A0 				;DE-REFERENCE IT
		CMP 	#10,RGNSIZE(A0) 			;IS RGNA RECTANGULAR ?
		BEQ.S	ARECT					;YES, SKIP IT
		ADD 	#2,D5					;NO, SET UP FLAG
		LEA 	STATEA(A6),A1				;POINT TO STATE RECORD A
		BSR.S	INITONE 				;INIT STATE, ALLOC BUFFER
ARECT
		MOVE.L	RGNB(A6),A0 			;GET RGNHANDLE
		MOVE.L	(A0),A0 				;DE-REFERENCE IT
		CMP 	#10,RGNSIZE(A0) 			;IS RGNB RECTANGULAR ?
		BEQ.S	BRECT					;YES, SKIP IT
		ADD 	#4,D5					;NO, BUMP FLAG
		LEA 	STATEB(A6),A1				;POINT TO STATE RECORD B
		BSR.S	INITONE 				;INIT STATE, ALLOC BUFFER
BRECT
		MOVE.L	RGNC(A6),A0 			;GET RGNHANDLE
		MOVE.L	(A0),A0 				;DE-REFERENCE IT
		CMP 	#10,RGNSIZE(A0) 			;IS RGNC RECTANGULAR ?
		BEQ.S	CRECT					;YES, SKIP IT
		ADD 	#8,D5					;NO, BUMP FLAG
		LEA 	STATEC(A6),A1				;POINT TO STATE RECORD C
		PEA 	CRECT					;PUSH FAKE RETURN ADDR
INITONE MOVE	MINRECT+LEFT(A6),D0 		;GET MINH
		MOVE	MINRECT+RIGHT(A6),D1			;GET MAXH
		MOVE	BUFLEFT(A6),D2				;GET BUFLEFT
		JMP 	INITRGN 				;INIT STATE, ALLOC BUFFER
CRECT


;---------------------------------------------------------------------
;
;  IF ONLY ONE REGION IS NON-RECTANGULAR, PLAY IT BACK DIRECTLY
;  INTO THE MASK BUFFER.
;
		MOVE.L	MASKBUF(A6),D7
		MOVE	D5,RECTFLAG(A6)
		CMP 	#2,D5					;IS RGNA THE ONLY NON-RECT ?
		BNE.S	AOK 				;NO, CONTINUE
		MOVE.L	D7,STATEA+SCANBUF(A6)			;YES, PLAY DIRECTLY INTO MASK
		BRA.S	COK
AOK 	CMP 	#4,D5					;IS RGNB THE ONLY NON-RECT ?
		BNE.S	BOK
		MOVE.L	D7,STATEB+SCANBUF(A6)
		BRA.S	COK
BOK 	CMP 	#8,D5					;IS RGNC THE ONLY NON-RECT ?
		BNE.S	COK
		MOVE.L	D7,STATEC+SCANBUF(A6)
COK


;----------------------------------------------------------
;
;  ASSUME WE WILL BE DRAWING DOWNWARD AND TO RIGHT.
;
		MOVE	MINRECT+TOP(A6),FIRSTV(A6)		;FIRSTV:=MINRECT TOP
		MOVE	MINRECT+BOTTOM(A6),LASTV(A6)	;LASTV:=MINRECT BOTTOM
		MOVE.L	#$00040001,HBUMP(A6)			;HBUMP:=4 BYTES, VBUMP:=1 SCAN
		MOVE	ROWBYTES(A4),D0
		EXT.L	D0
		MOVE.L	D0,DSTROW(A6)				;DSTROW:=+ROWBYTES
		MOVE.L	D7,MASKADDR(A6) 			;MASKADDR:=MASKBUF


;---------------------------------------
;
;  SET UP INVERT FLAG IN D7 TO REFLECT MODE BIT 2
;
		CLR.L	D7					;SAY NOT INVERTED
		MOVE	MODE(A6),D2 			;GET TRANSFER MODE
		BMI 	DONE					;QUIT IF MODE NEGATIVE
		BCLR	#2,D2					;TEST AND CLR INVERT BIT
		BEQ.S	SETMODE 				;SKIP IF NOT INVERTED
		NOT.L	D7					;INVERTED; D7 GETS ALL 1'S


;--------------------------------------------------
;
;  CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES
;
SETMODE AND 	#$F,D2					;TREAT MODE MOD 16
		MOVEQ	#3,D0
		AND 	D2,D0					;GET BOTTOM 2 BITS OF MODE
		ADD 	D0,D2					;MODIFY MODE FOR INDEX
		LEA 	MODETAB,A0				;POINT TO MODE TABLE
		ADD 	0(A0,D2),A0 			;GET CASE JUMP ADDRESS
		MOVE.L	A0,MODECASE(A6) 			;SAVE FOR LATER

		BTST	#3,D2					;WILL PATTERN BE USED ?
		BEQ.S	USESRC					;NO, USE SOURCE INSTEAD


;------------------------------------------------------------------
;
;  PATTERN WILL BE USED.  EXPAND 8 BYTE PATTERN TO 16 LONGS
;
		MOVE	BOUNDS+LEFT(A4),D2			;GET GLOBAL-LOCAL OFFSET
		MOVE.L	PAT(A6),A0				;POINT TO BYTE WIDE PATTERN
		LEA 	EXPAT(A6),A1				;POINT TO EXPANDED PATTERN
		JSR 	PATEXPAND				;EXPAND 8 BYTES TO 16 LONGS


;-------------------------------------------------
;
;  SET UP (VERT * 4) MOD 64 AS PATTERN SELECTOR
;
		MOVEQ	#$F,D7					;TREAT COORD MOD 16
		AND 	MINRECT+TOP(A6),D7			;GET TOP VERT COORD
		LSL 	#2,D7					;QUAD FOR 4 BYTE PATTERNS
		MOVE.L	EXPAT(A6,D7),D6 			;GET FIRST PATTERN DATA
		BRA 	GETDST				 ;SKIP OVER SRC STUFF


;--------------------------------------------------------------
;
;  SRC WILL BE USED.  CHECK FOR OVERLAP AND CHOOSE DIRECTION SO
;  THAT SRC WONT GET CLOBBERED BEFORE IT IS USED.
;
USESRC	MOVE.L	DSTRECT(A6),A1				;POINT TO DSTRECT
		MOVE.L	SRCRECT(A6),A2				;POINT TO SRCRECT
		MOVE.L	SRCBITS(A6),A3				;POINT TO SRCBITS
		MOVE	ROWBYTES(A3),D0
		EXT.L	D0
		MOVE.L	D0,SRCROW(A6)				;SRCROW:=+ROWBYTES
		MOVE.L	BASEADDR(A3),D0 			;GET SRC BASEADDR
		CMP.L	BASEADDR(A4),D0 			;ARE SRC AND DST SAME BITMAP ?
		BNE.S	SRCOK					;NO, DON'T WORRY ABOUT OVERLAP

		MOVE	TOP(A1),D0				;GET DST TOP
		SUB 	BOUNDS+TOP(A4),D0			;CONVERT TO GLOBAL
		MOVE	TOP(A2),D1				;GET SRC TOP
		SUB 	BOUNDS+TOP(A3),D1			;CONVERT TO GLOBAL
		SUB 	D1,D0					;CALC DV:=DSTTOP-SRCTOP
		BLT.S	SRCOK					;EVERYTHING FINE IF SCROLLING UP
		BGT.S	UPSIDE					;UPSIDE DOWN IF SCROLLING DOWN


;------------------------------------------------------------
;
;  DV=0. IF DH > 0 THEN WE MUST TRANSFER BACKWARDS FROM RIGHT.
;
		MOVE	LEFT(A1),D0 			;GET DST LEFT
		SUB 	BOUNDS+LEFT(A4),D0			;CONVERT TO GLOBAL
		MOVE	LEFT(A2),D1 			;GET SRC LEFT
		SUB 	BOUNDS+LEFT(A3),D1			;CONVERT TO GLOBAL
		SUB 	D1,D0					;DH := DSTLEFT-SRCLEFT
		BLE.S	SRCOK					;IF DH <= 0, WE'RE FINE
		NEG 	HBUMP(A6)				;ELSE BUMP TOWARD LEFT
		BRA.S	SRCOK					;CONTINUE


;------------------------------------------------------------
;
;  DV IS POSITIVE, WE MUST TRANSFER UPSIDE-DOWN FROM BOTTOM.
;
UPSIDE	NEG 	VBUMP(A6)				;VBUMP:=-1, BUMP UPWARD
		NEG.L	SRCROW(A6)				;SRCROW:=-SRC ROWBYTES
		NEG.L	DSTROW(A6)				;DSTROW:=-DST ROWBYTES
		MOVE	MINRECT+BOTTOM(A6),FIRSTV(A6)
		SUB 	#1,FIRSTV(A6)				;FIRSTV:=BOTTOM-1
		MOVE	MINRECT+TOP(A6),LASTV(A6)
		SUB 	#1,LASTV(A6)				;LASTV:=TOP-1


;----------------------------------------------
;
;  CALC SHIFTCNT
;
SRCOK	MOVE	LEFT(A1),D6 			;GET DST LEFT LOCAL COORDS
		SUB 	BOUNDS+LEFT(A4),D6			;CONVERT TO GLOBAL
		MOVE	LEFT(A2),D1 			;GET SRC LEFT LOCAL COORDS
		SUB 	BOUNDS+LEFT(A3),D1			;CONVERT TO GLOBAL
		SUB 	D1,D6					;CALC DELTA HORIZ GLOBAL
		AND 	#$F,D6					;MOD 16 FOR SHIFTCNT


;------------------------------------
;
;  CALC STARTING SRCADDR
;
		MOVE	FIRSTV(A6),D0				;GET FIRST DST VERTICAL
		SUB 	TOP(A1),D0				;SUBTRACT DSTRECT TOP
		ADD 	TOP(A2),D0				;ADD SRCRECT TOP
		SUB 	BOUNDS+TOP(A3),D0			;CONVERT SRCV TO GLOBAL
		MULU	ROWBYTES(A3),D0 			;MULT BY SRC ROWBYTES
		MOVE.L	BASEADDR(A3),A0 			;GET START OF BITMAP
		ADD.L	D0,A0					;ADD OFFSET TO BASEADDR

		MOVE	MINRECT+LEFT(A6),D0 		;GET DST LEFT
		SUB 	LEFT(A1),D0 			;CONVERT FROM DST COORDS
		ADD 	LEFT(A2),D0 			;TO SRC COORDS
		SUB 	BOUNDS+LEFT(A3),D0			;CONVERT TO GLOBAL SRC
		ADD 	D6,D0					;ADD SHIFTCNT
		LSR 	#4,D0					;CONVERT DOTS TO WORDS
		ADD 	D0,D0					;DOUBLE FOR BYTES
		ADD 	D0,A0					;ADD HORIZ OFFSET
		MOVE.L	A0,SRCADDR(A6)				;SAVE AS SRCADDR


;------------------------------------
;
;  CALC STARTING DSTADDR
;
GETDST	MOVE	FIRSTV(A6),D0				;GET FIRST DST VERT
		SUB 	BOUNDS+TOP(A4),D0			;CONVERT TO GLOBAL
		MULU	ROWBYTES(A4),D0 			;MULT BY ROWBYTES
		MOVE.L	BASEADDR(A4),A0 			;GET START OF BITMAP
		ADD.L	D0,A0					;ADD VERTICAL OFFSET

		MOVE	MINRECT+LEFT(A6),D0 		;GET DST LEFT
		SUB 	BOUNDS+LEFT(A4),D0			;CONVERT TO GLOBAL
		LSR 	#4,D0					;CONVERT DOTS TO WORDS
		ADD 	D0,D0					;DOUBLE FOR BYTES
		ADD 	D0,A0					;ADD HORIZ OFFSET
		MOVE.L	A0,DSTADDR(A6)				;SAVE AS DSTADDR



;------------------------------------------------------------------------
;
;  ADJUST SRCADDR,DSTADDR,MASKADDR IF WE ARE BUMPING BACKWARDS FROM RIGHT
;
		TST 	HBUMP(A6)				;BUMPING BACKWARD ?
		BPL.S	HBUMPOK 				;NO, CONTINUE
		MOVE	BUFSIZE(A6),D0				;GET BUFFER SIZE
		ASL 	#2,D0					;QUAD FOR # BYTES
		EXT.L	D0					;CLEAR HI WORD
		ADD.L	D0,DSTADDR(A6)				;ADJUST DSTADDR
		ADD.L	D0,SRCADDR(A6)				;ADJUST SRCADDR
		ADD.L	D0,MASKADDR(A6) 			;ADJUST MASKADDR
HBUMPOK


		MOVE	FIRSTV(A6),VERT(A6) 		;INIT CURRENT VERTICAL
;-------------------------------------------------------
;
;  MAKE MASK BUFFER CURRENT FOR THIS VERTICAL.
;  THEN SET UP AND DRAW CURRENT SCANLINE.
;
NXTMASK JSR 	SEEKMASK				;MAKE MASK BUFFER CURRENT
		MOVE.L	SRCADDR(A6),A3				;INIT SRCPTR
		MOVE.L	DSTADDR(A6),A5				;INIT DSTPTR FOR ROW
		MOVE.L	MASKADDR(A6),A4 			;INIT MASKPTR FOR ROW
		MOVE	BUFSIZE(A6),D2				;INIT COUNT OF LONGS
		MOVE.L	MODECASE(A6),A2 			;GET MODE CASE JUMP
		JMP 	(A2)					;TAKE MODE JUMP

NEXTSRC MOVE.L	SRCROW(A6),D0				;GET SRC ROWBYTES
		ADD.L	D0,SRCADDR(A6)				;BUMP SRC TO NEXT ROW
		BRA.S	BUMPV					;CONTINUE WITH NEXT ROW

NEXTPAT ADD 	#4,D7					;BUMP PATTERN SELECTOR
		AND 	#$3F,D7 				;MOD 64 FOR 16 LONG REPEAT
		MOVE.L	EXPAT(A6,D7),D6 			;GET PATTERN FOR NEXT ROW


;-----------------------------------------------------
;
;  BUMP DESTINATION VERTICALLY AND LOOP FOR ALL ROWS
;
BUMPV	MOVE.L	DSTROW(A6),D0				;GET DST ROWBYTES
		ADD.L	D0,DSTADDR(A6)				;BUMP DST TO NEXT ROW
NODRAW	MOVE	VERT(A6),D0 			;GET CURRENT VERT
		ADD 	VBUMP(A6),D0				;BUMP UP OR DOWN A SCAN LINE
		MOVE	D0,VERT(A6) 			;UPDATE CURRENT VERT
		CMP 	LASTV(A6),D0				;ARE WE AT THE LAST SCAN LINE ?
		BNE 	NXTMASK 				;NO, LOOP FOR ALL SCAN LINES


;-----------------------------------------------------------------
;
;  ENTIRE RGNBLT COMPLETE. RESTORE REGS AND STACK AND GO HOME.
;
DONE	MOVE.L	SAVEA5(A6),A5				;GET GLOBAL POINTER
		JSR 	SHOWCURSOR				;RESTORE CURSOR
GOHOME	MOVE.L	SAVESTK(A6),SP				;STRIP VARIABLE SIZED BUFFER
		MOVEM.L (SP)+,D0-D7/A2-A5			;RESTORE REGISTERS
		UNLINK	PARAMSIZE,'RGNBLT  '



;-----------------------------------------------------------------
;
;  LOCAL ROUTINE TO UPDATE MASK BUFFER TO CURRENT VERTICAL COORD.
;
SEEKMASK MOVE	VERT(A6),D0 			;GET CURRENT VERT COORD
		 MOVE	RECTFLAG(A6),D1 			;GET RECTFLAG = 0,2,4
		 MOVE	RECTJMP(D1),D1				;GET OFFSET FROM TABLE
		 JMP	RECTJMP(D1) 			;TAKE CASE JUMP

RECTJMP DC.W	SEEKOK-RECTJMP
		DC.W	A-RECTJMP
		DC.W	B-RECTJMP
		DC.W	AB-RECTJMP
		DC.W	C-RECTJMP
		DC.W	AC-RECTJMP
		DC.W	BC-RECTJMP
		DC.W	ABC-RECTJMP


;--------------------------------------------------------------------
;
;  ONLY REGION A IS NON RECTANGULAR.  UPDATE IT AND USE IT AS THE MASK
;
A		LEA 	STATEA(A6),A1
		BRA.S	JMPSEEK


;--------------------------------------------------------------------
;
;  ONLY REGION B IS NON RECTANGULAR.  UPDATE IT AND USE IT AS THE MASK
;
B		LEA 	STATEB(A6),A1
		BRA.S	JMPSEEK


;--------------------------------------------------------------------
;
;  ONLY REGION C IS NON RECTANGULAR.  UPDATE IT AND USE IT AS THE MASK
;
C		LEA 	STATEC(A6),A1
JMPSEEK MOVE.L	MASKBUF(A6),SCANBUF(A1) 		;PLAY DIRECTLY INTO MASKBUF
		JMP 	SEEKRGN


;-------------------------------------------------------------------
;
;  REGIONS A AND B ARE NON-RECTANGULAR. UPDATE EACH,
;  THEN FORM INTERSECTION IN THE MASK BUFFER.
;
AB		LEA 	STATEA(A6),A1
		JSR 	SEEKRGN
		MOVE	D1,-(SP)				;REMEMBER IF RGN CHANGED
		LEA 	STATEB(A6),A1
		JSR 	SEEKRGN
		OR		(SP)+,D1				;HAS EITHER RGN CHANGED ?
		BEQ.S	SEEKOK					;NO, WE'RE DONE
		MOVE.L	STATEA+SCANBUF(A6),A0
		MOVE.L	STATEB+SCANBUF(A6),A1
		BRA.S	CPY2BUF


;-------------------------------------------------------------------
;
;  REGIONS A AND C ARE NON-RECTANGULAR. UPDATE EACH,
;  THEN FORM INTERSECTION IN THE MASK BUFFER.
;
AC		LEA 	STATEA(A6),A1
		JSR 	SEEKRGN
		MOVE	D1,-(SP)				;REMEMBER IF RGN CHANGED
		LEA 	STATEC(A6),A1
		JSR 	SEEKRGN
		OR		(SP)+,D1				;HAS EITHER RGN CHANGED ?
		BEQ.S	SEEKOK					;NO, WE'RE DONE
		MOVE.L	STATEA+SCANBUF(A6),A0
		MOVE.L	STATEC+SCANBUF(A6),A1
		BRA.S	CPY2BUF


;-------------------------------------------------------------------
;
;  REGIONS B AND C ARE NON-RECTANGULAR. UPDATE EACH,
;  THEN FORM INTERSECTION IN THE MASK BUFFER.
;
BC		LEA 	STATEB(A6),A1
		JSR 	SEEKRGN
		MOVE	D1,-(SP)				;REMEMBER IF RGN CHANGED
		LEA 	STATEC(A6),A1
		JSR 	SEEKRGN
		OR		(SP)+,D1				;HAS EITHER RGN CHANGED ?
		BEQ.S	SEEKOK					;NO, WE'RE DONE
		MOVE.L	STATEB+SCANBUF(A6),A0
		MOVE.L	STATEC+SCANBUF(A6),A1
CPY2BUF MOVE.L	MASKBUF(A6),A2
		MOVE	BUFSIZE(A6),D1
BCLOOP	MOVE.L	(A0)+,D0
		AND.L	(A1)+,D0
		MOVE.L	D0,(A2)+
		DBRA	D1,BCLOOP
SEEKOK	RTS 					;ALL 3 ARE RECT, DO NOTHING


;-------------------------------------------------------------------
;
;  REGIONS A, B AND C ARE ALL NON-RECTANGULAR. UPDATE EACH,
;  THEN FORM INTERSECTION IN THE MASK BUFFER.
;
ABC 	LEA 	STATEA(A6),A1
		JSR 	SEEKRGN
		MOVE	D1,-(SP)				;REMEMBER IF RGN CHANGED
		LEA 	STATEB(A6),A1
		JSR 	SEEKRGN
		OR		D1,(SP) 				;REMEMBER IF RGN CHANGED
		LEA 	STATEC(A6),A1
		JSR 	SEEKRGN
		OR		(SP)+,D1				;HAS EITHER RGN CHANGED ?
		BEQ.S	ABCDONE 				;NO, WE'RE DONE
		MOVE.L	STATEA+SCANBUF(A6),A0
		MOVE.L	STATEB+SCANBUF(A6),A1
		MOVE.L	STATEC+SCANBUF(A6),A2
		MOVE.L	MASKBUF(A6),A3
		MOVE	BUFSIZE(A6),D1
ABCLOOP MOVE.L	(A0)+,D0
		AND.L	(A1)+,D0
		AND.L	(A2)+,D0
		MOVE.L	D0,(A3)+
		DBRA	D1,ABCLOOP
ABCDONE RTS


;---------------------------------------------------------------;
;									;
;  INTERFACE TO EACH OF THE RGNBLT SCANLINE LOOPS:			;
;									;
;  REGISTERS:	A0: 			D0: 			;
;			A1: 			D1: 			;
;			A2: 			D2: LONGCNT 		;
;			A3: SRCPTR			D3: 			;
;			A4: MASKPTR 		D4: 			;
;			A5: DSTPTR			D5: 			;
;			A6: 			D6: SHIFTCNT OR PATTERN ;
;			A7: 			D7: INVERT OR PAT-SEL	;
;									;
;---------------------------------------------------------------;

MODETAB DC.W	 MASK0-MODETAB
		DC.W	 MASK1-MODETAB
		DC.W	 MASK2-MODETAB
		DC.W	 MASK3-MODETAB
		DC.W	 MASK8-MODETAB
		DC.W	 MASK9-MODETAB
		DC.W	 MASK10-MODETAB
		DC.W	 MASK11-MODETAB


;-------------------------------------------------------
;
;  MODE 0 OR 4: SRC --> DST
;
MASK0	MOVE.L	-2(A3),D0		;GET SRC FROM BITMAP
		LSR.L	D6,D0			;ALIGN TO DST
		SWAP	D0			;PUT INTO HI HALF OF D0
		MOVE.L	(A3),D1 		;GET SRC FROM BITMAP
		ADD 	HBUMP(A6),A3	;BUMP 4 BYTES RIGHT OR LEFT
		LSR.L	D6,D1			;ALIGN TO DST
		MOVE	D1,D0			;ASSEMBLE ONE LONG
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		MOVE.L	(A4),D1 		;GET MASK
		ADD 	HBUMP(A6),A4	;BUMP 4 BYTES RIGHT OR LEFT
		AND.L	D1,D0			;MASK SRC
		NOT.L	D1			;FORM NOTMASK
		AND.L	(A5),D1 		;GET DST DATA
		OR.L	D1,D0			;MERGE WITH SRC DATA
		MOVE.L	D0,(A5) 		;PUT RESULT IN DST
		ADD 	HBUMP(A6),A5	;BUMP 4 BYTES RIGHT OR LEFT
		DBRA	D2,MASK0		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTSRC 		;GO FOR NEXT ROW


;-------------------------------------------------------
;
;  MODE 1 OR 5: SRC OR DST --> DST
;
MASK1	MOVE.L	-2(A3),D0		;GET SRC FROM BITMAP
		LSR.L	D6,D0			;ALIGN TO DST
		SWAP	D0			;PUT INTO HI HALF OF D0
		MOVE.L	(A3),D1 		;GET SRC FROM BITMAP
		ADD 	HBUMP(A6),A3	;BUMP 4 BYTES RIGHT OR LEFT
		LSR.L	D6,D1			;ALIGN TO DST
		MOVE	D1,D0			;ASSEMBLE ONE LONG
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		AND.L	(A4),D0 		;AND WITH MASK
		ADD 	HBUMP(A6),A4	;BUMP 4 BYTES RIGHT OR LEFT
		OR.L	D0,(A5) 		;OR RESULT INTO DST
		ADD 	HBUMP(A6),A5	;BUMP 4 BYTES RIGHT OR LEFT
		DBRA	D2,MASK1		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTSRC 		;LOOP FOR NEXT ROW


;-------------------------------------------------------
;
;  MODE 2 OR 6: SRC XOR DST --> DST
;
MASK2	MOVE.L	-2(A3),D0		;GET SRC FROM BITMAP
		LSR.L	D6,D0			;ALIGN TO DST
		SWAP	D0			;PUT INTO HI HALF OF D0
		MOVE.L	(A3),D1 		;GET SRC FROM BITMAP
		ADD 	HBUMP(A6),A3	;BUMP 4 BYTES RIGHT OR LEFT
		LSR.L	D6,D1			;ALIGN TO DST
		MOVE	D1,D0			;ASSEMBLE ONE LONG
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		AND.L	(A4),D0 		;AND WITH MASK
		ADD 	HBUMP(A6),A4	;BUMP 4 BYTES RIGHT OR LEFT
		EOR.L	D0,(A5) 		;XOR RESULT INTO DST
		ADD 	HBUMP(A6),A5	;BUMP 4 BYTES RIGHT OR LEFT
		DBRA	D2,MASK2		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTSRC 		;LOOP FOR NEXT ROW


;-------------------------------------------------------
;
;  MODE 3 OR 7: SRC BIC DST --> DST
;
MASK3	MOVE.L	-2(A3),D0		;GET SRC FROM BITMAP
		LSR.L	D6,D0			;ALIGN TO DST
		SWAP	D0			;PUT INTO HI HALF OF D0
		MOVE.L	(A3),D1 		;GET SRC FROM BITMAP
		ADD 	HBUMP(A6),A3	;BUMP 4 BYTES RIGHT OR LEFT
		LSR.L	D6,D1			;ALIGN TO DST
		MOVE	D1,D0			;ASSEMBLE ONE LONG
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		AND.L	(A4),D0 		;AND WITH MASK
		ADD 	HBUMP(A6),A4	;BUMP 4 BYTES RIGHT OR LEFT
		NOT.L	D0			;INVERT FOR BIC
		AND.L	D0,(A5) 		;BIC RESULT INTO DST
		ADD 	HBUMP(A6),A5	;BUMP 4 BYTES RIGHT OR LEFT
		DBRA	D2,MASK3		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTSRC 		;LOOP FOR NEXT ROW


;-------------------------------------------------------
;
;  MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES)
;
MASK8	MOVE.L	D6,D0			;GET PATTERN DATA
		MOVE.L	(A4)+,D1		;GET MASK
		AND.L	D1,D0			;MASK PATTERN DATA
		NOT.L	D1			;MAKE NOTMASK
		AND.L	(A5),D1 		;GET DST DATA
		OR.L	D1,D0			;MERGE WITH PAT DATA
		MOVE.L	D0,(A5)+		;PUT RESULT TO DST
		DBRA	D2,MASK8		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTPAT 		;LOOP BACK FOR NEXT ROW


;-------------------------------------------------------
;
;  MODE 9 OR 13: PATTERN OR DST --> DST
;
MASK9	MOVE.L	D6,D0			;GET PATTERN DATA
		AND.L	(A4)+,D0		;MASK PATTERN DATA
		OR.L	D0,(A5)+		;OR RESULT INTO DST
		DBRA	D2,MASK9		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTPAT 		;LOOP BACK FOR NEXT ROW


;-------------------------------------------------------
;
;  MODE 10 OR 14: PATTERN XOR DST --> DST (INVERTING AREAS, XOR LINES)
;
MASK10	MOVE.L	D6,D0			;GET PATTERN DATA
		AND.L	(A4)+,D0		;MASK PATTERN DATA
		EOR.L	D0,(A5)+		;XOR RESULT INTO DST
		DBRA	D2,MASK10		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTPAT 		;LOOP BACK FOR NEXT ROW


;-------------------------------------------------------
;
;  MODE 11 OR 15: PATTERN BIC DST --> DST
;
MASK11	MOVE.L	D6,D0			;GET PATTERN DATA
		AND.L	(A4)+,D0		;MASK PATTERN DATA
		NOT.L	D0			;INVERT FOR BIC
		AND.L	D0,(A5)+		;BIC RESULT INTO DST
		DBRA	D2,MASK11		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTPAT 		;LOOP BACK FOR NEXT ROW




		END