QuickDraw/RgnBlt.a

826 lines
34 KiB
Plaintext
Executable File

.INCLUDE GRAFTYPES.TEXT
;------------------------------------------------------------------
;
; --> RGNBLT.TEXT
;
; Low level block transfer clipped to an arbitrary region.
;
.PROC RgnBlt,9
.REF BitBlt,RSect,ShieldCursor,ShowCursor
.REF 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 D3-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)+,D3-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 .WORD SEEKOK-RECTJMP
.WORD A-RECTJMP
.WORD B-RECTJMP
.WORD AB-RECTJMP
.WORD C-RECTJMP
.WORD AC-RECTJMP
.WORD BC-RECTJMP
.WORD 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 .WORD MASK0-MODETAB
.WORD MASK1-MODETAB
.WORD MASK2-MODETAB
.WORD MASK3-MODETAB
.WORD MASK8-MODETAB
.WORD MASK9-MODETAB
.WORD MASK10-MODETAB
.WORD 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