mac-rom/QuickDraw/Classic/RgnBlt.m.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

842 lines
25 KiB
Plaintext

;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