; ; File: RgnBlt.a ; ; Contains: Low level block transfer clipped to an arbitrary region. ; Called by StretchBits only. ; ; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved. ; ; This file is used in these builds: Mac32 Bigbang Sys606 ; ; Change History (most recent first): ; ; 6/3/93 CSS Per Shannon Holland and KON, The code RgnBlt checks for a ; pattern which is solid background color when it should check for ; a pattern which is a solid foreground color. ; 01/06/93 HI #1052740: Modified D0 to D3 in RgnBlt in rcMASK0 section. ; Previously, it was masking out the destination instead of ; the source; so the images were drawn incorrectly. ANDing ; with D3 masks out the source and fixes the bug. (Hoon Im) ; 6/12/92 stb stb Synch with QDciPatchROM.a; added comments to ; rMASK8, rXMASK8, rslowHilite, rTransparent. ; <11> 11/26/90 SMC Fixed pattern hiliting once and for all. With BAL. ; <10> 10/31/90 SMC Fixed alpha channel bugs with BAL. ; <9> 10/18/90 SMC Made speed/size improvements to rcMASK0,1,3. With KON. ; <8> 9/26/90 SMC Removed optimization in rTransparent that was losing pattern ; data. Also removed jmp to next instruction in rslowHilite. ; <7> 9/18/90 BG Removed <3>. 040s are behaving more reliably now. ; <6> 8/20/90 SMC Changed use of pattern offset in big pattern copy (rXMASK8) from ; signed to unsigned. ; <5> 8/1/90 SMC Added real non-black pattern and source hilite mode blit loop. ; <4> 7/20/90 gbm Change a few identifiers so conflicts go away ; <3> 6/27/90 BG Added EclipseNOPs for flakey 040s. ; <2> 5/24/90 KON Remove checks on BGnotWhite, and add slop factor to stack frame. ; <1.7> 11/18/89 BAL Incorporated QuickerDraw's 8-bit arithmetic transfer loops ; <•1.6> 7/14/89 BAL For Aurora: Final CQD ; <1.5> 6/30/89 BAL Now uses qdStackXtra equate. ; <•1.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final ; <•1.3> 4/12/89 BAL Blasting in 32-Bit QuickDraw 1.0B1 ; 11/5/88 BAL Set transfer direction (RUNBUMP) for seekMask. ; 9/22/88 BAL Moved initialization of region state records into GetSeek. ; 9/21/88 BAL Added allocation of RUNBUF for new run-based clipping ; 9/18/88 BAL Altered to use common stack frame file 'Drawing Vars.a' ; 11/8/87 BAL Fixed computation of bufSize for more accurate region clipping ; at at depths greater than 1. ;_______________________________ Post Mac II ____________________________________________ ; 12/12/86 CRC Added arithmetic modes ; 7/29/86 EHB Use new stack-based EXPAT buffer ; 7/24/86 EHB Added support for patterns wider than one long ; 7/22/86 EHB Added color to pattern OR and pattern BIC transfer modes ; 7/5/86 EHB New routine GetSeek replaces seekMask and getXRtn ; 6/24/86 EHB Big re-org: all shared fields set up by stretchbits before ; calling here. All parms in stack frame or registers. ; 6/22/86 EHB Call new patexpand for patterns with depths ; 6/20/86 EHB New params to COLORMAP Added FCOLOR and BCOLOR to stack frame ; 6/19/86 EHB Do horiz calculations as longs for big pixels Removed SRCPIX and ; DSTPIX from frame, since always called with pixMaps as params ; (by StretchBits). ; 6/15/86 EHB Modified to use longword aligned buffers (Missed it before!) If ; one 1-bit region, play directly into RGNBUFFER Convert BitsToPix ; and use pixelSize Make sure stack is longword aligned (for fast ; buffers) ; 6/14/86 EHB Call GetXRtn to set expand routine for SeekMask Added SRCPIX and ; DSTPIX to stack frame ; 6/13/86 EHB Moved SeekMask to another file Rearranged stack frame with ; SeekMask stuff at top ; 6/8/86 EHB Took HBUMP out of inner loop (use D3 instead). Use BFEXTU to ; extract aligned longs in scanline loops ; 6/5/86 EHB Masked off flag bits in all references to rowBytes BLANKS ON STRING ASIS MACHINE MC68020 RgnBlt PROC EXPORT EXPORT rMASK0, rMASK1, rMASK2, rMASK3, rMASK8, rMASK9, rMASK10, rMASK11, rXMASK8 EXPORT rXMASK9, rXMASK10, rXMASK11, rAvg, rAddPin, rAddOver, rSubPin, rTransparent EXPORT rMax, rSubOver, rMin, rcMask0, rcMask1, rslowHilite, rcMask3, rHilite EXPORT rArith16Tab, rArith32Tab, rHiliteTab ;-------------------------------------------------------------- ; ; PROCEDURE RgnBlt(srcPix,dstPix: PixMap; ; 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. ; ; STRECHBITS DOES ALL TRANSFERS BETWEEN SOURCE AND DESTINATION OF DIFFERENT ; DEPTHS, SO WE CAN ASSUME THAT SOURCE DEPTH = DEST DEPTH. ; ; COPYRIGHT APPLE COMPUTER INC. ; DESIGNED AND WRITTEN BY BILL ATKINSON ; ; THIS CODE IS POSITION INDEPENDENT, RE-ENTRANT, AND READ-ONLY. ; CLOBBERS ONLY A0. ; ; mode bit meaning ; 7 6 5 4 3 2 1 0 ; 0 msk ari hil pat not coxb- ; ; 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 ; ; 16 … 31 unassigned (but 16 is used temporarily to note that hiliting is fast) ; ; 32 AVG(SRC, DST, WEIGHT) --> DST ; 33 SRC + DST --> DST (pin TO MAX) ; 34 SRC + DST --> DST (no pin) ; 35 DST - SRC --> DST (pin TO MIN) ; 36 SRC less bg --> DST ; 37 MAX(SRC, DST) --> DST ; 38 DST - SRC --> DST (no pin) ; 39 MIN(SRC, DST) --> DST ; 40 AVG(PAT, DST, WEIGHT) --> DST ; 41 PAT + DST --> DST (pin TO MAX) ; 42 PAT + DST --> DST (no pin) ; 43 DST - PAT --> DST (pin TO MIN) ; 44 PAT less bg --> DST ; 45 MAX(PAT, DST) --> DST ; 46 DST - PAT --> DST (no pin) ; 47 MIN(PAT, DST) --> DST ; 48 … 49 unassigned ; 50 src as mask, Hilite Dst (bg color <--> hilite color) ; 51 … 57 unassigned ; 58 pat as mask, Hilite Dst (bg color <--> hilite color) ;---------------------------------------------------- ; ; A6 OFFSETS OF PARAMETERS AFTER LINK: ; PARAMSIZE EQU 44 ;SIZE OF PARAMETERS SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP MASKBITS EQU SRCBITS-4 ;LONG, ADDR OF BITMAP DSTBITS EQU MASKBITS-4 ;LONG, ADDR OF BITMAP SRCRECT EQU DSTBITS-4 ;LONG, ADDR OF RECT MASKRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT DSTRECT EQU MASKRECT-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 multColor EQU RGNC-2 ;byte set if source contains non black/white colors ;---------------------------------------------------- ; ; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK: ; ; STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS. ; &CurFile SETC 'RGNBLT' INCLUDE 'DrawingVars.a' ;-------------------------------------------------------------- ; ; RGNBLT CALLED WITH STACK FRAME SET UP AS SHOWN ABOVE. ; CALLER TAKES CARE OF CURSOR ; ; REGISTER USE: ; ; A2: SRCRECT ; A3: DSTRECT ; A4: SRCPIX ; A5: DSTPIX ; ; D3: SRCSHIFT ; D4: DSTSHIFT ; D7: INVERTFLAG ; ; ONLY A6,A7 MUST BE PRESERVED ;----------------------------------- ; ; SAVE STACK FOR NOW, BECAUSE WE'RE STILL ALLOCATING SCANLINE BUFFERS ; MOVE.L SP,SAVESTK2(A6) ;PRESERVE STACK POINTER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; RgnBlt and everyone else (stretch,drawline,drawarc) compute bufSize as: ; ; [ (minRect.right-minRect.left) div 32 + 1 ] * pixelsize - 1 ; ; This will result in an excess of upto (pixelsize-1) longs to be accessed during the ; region masked drawing. Since region masks are created as long aligned 1-bit deep masks ; which are then expanded to the proper depth the RGNBUFFER on the stack must be the bulky ; size computed above (until seekMask is changed to be more intelligent) but the stackFrame ; variable bufSize which determines the width of the scanline actually written to can more ; accurately be computed as: ; ; [ (minRect.right-minRect.left) * pixelsize - 1 ] div 32 08Nov87 BAL ; ;----------------------------------- ; ; CALC BUFLEFT AND BUFSIZE (BUFSIZE = DSTSIZE) ; MOVE MINRECT+LEFT(A6),D1 ;GET MINRECT LEFT SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL COORDS EXT.L D1 ;CLEAR HI WORD LSL.L D4,D1 ;CONVERT PIXELS TO BITS AND #$FFE0,D1 ;TRUNC TO MULT OF 32 LSR.L D4,D1 ;CONVERT BITS TO PIXELS ADD BOUNDS+LEFT(A5),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 (=SCANSIZE) move d0,d1 ;save for expansion scanline buffer ext.l d1 ;clear out high word lsl.l d4,d1 ;convert to bits subq.l #1,d1 ;force downward round LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 LSR #5,D0 ;get (pixels in scanbuf)/32 ADDQ #1,D0 ;MAKE IT ONE BASED LSL D4,D0 ;MULTIPLY BY DEPTH ; SUBQ #1,D0 ;MAKE SIZE 0 BASED addQ #4,D0 ;add in slop for 4-bit ;----------------------------------------------------------------------- ; ; 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,RGNBUFFER(A6) ;REMEMBER WHERE RGNBUFFER IS ;-------------------------------------------------------------------- ; ; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION ; GET SEEK ROUTINE INTO SEEKMASK(A6) ; GET EXPAND ROUTINE INTO EXRTN(A6) FOR SEEK ROUTINE ; Clobbers: A0-A3, D0-D4 ; MOVEQ #-1,D0 ;assume run clipping Start of <11> MOVE LOCMODE(A6),D2 ;GET TRANSFER MODE CMP #32,D2 ;new arithmetic mode? BLO @newWay CMP #64,D2 BHS Done ;unimplemented mode CMP #48,D2 BLT.S @noHilite CMP #50,D2 ;source highlight mode? BEQ.S @oldWay ;if so, can't be fast pattern case CMP #58,D2 ;pattern highlight mode? BNE Done ;if not, it is unimplemented TST PATROW(A6) ;BIG PATTERN? BNE.S @oldWay ;if so, assume pattern contains background color MOVE.L exPat(A6),A0 ;check if non-background pattern MOVE.L FCOLOR(A6),D1 ;get foreground color CSS MOVEQ #$0F,D0 ;number of longs in a short pattern @nextPatRow CMP.L (A0)+,D1 ;is the row non-background? DBEQ D0,@nextPatRow ;if so, check for more rows BNE.S @oldWay ;if not, can’t do fast hiliting CSS MOVE #$10,locMode(A6) ;set the mode to the fast hilite variety BRA.S @newWay ;assume D0 = -1 @noHilite CMP.W #4,d4 ;is dst 16 or 32 bits/pixel? BGE.S @newWay ;yes, handle new way CMP.W #32,D2 ;is it an arithmetic mode? BLT.S @newWay ;no, handle new way CMP.W #47,D2 ;is it an arithmetic mode? BGT.S @newWay ;no, handle new way (hilite mode) @oldWay MOVEQ #0,D0 ;don't use run clipping @newWay ; End of <11> move.l d0,runBuf(a6) ;set non-zero for run clipping <1.5> BAL MOVE.L RGNC(A6),-(SP) ;PUSH USER RGNHANDLE MOVE.L RGNB(A6),-(SP) ;PUSH VIS RGNHANDLE MOVE.L RGNA(A6),-(SP) ;PUSH CLIP RGNHANDLE MOVE.L #2,-(SP) ;PUSH HANDLE COUNT - 1 _GETSEEK ;GET EXPAND ROUTINE INTO EXRTN(A6) ;AND SEEK ROUTINE INTO SEEKMASK(A6) MOVE.W DSTSHIFT(A6),D4 ;RESTORE DSTSHIFT MOVE.L DSTRECT(A6),A3 ;RESTORE DSTRECT ;---------------------------------------------------------- ; ; 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.L RGNBUFFER(A6),RGNADDR(A6) ;RGNADDR:=RGNBUFFER ScaleColorBit EQU 3 SwapFGBGBit EQU 4 UseStretchBit EQU 5 InvertItBit EQU 7 ColorizeInModeCaseBit EQU 8 ColorizeInSrcBufBit EQU 9 ;-------------------------------------------------- ; ; CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES ; GET INVERTFLAG INTO D7 ; SETMODE MOVE LOCMODE(A6),D2 ;GET TRANSFER MODE MOVE D2,D1 ;SAVE MODE CMP.W #$10,D2 ;fast hilite mode? <11> BNE.S @notFastHilite ; <11> MOVE.L rHiliteTabPtr,A0 ;get address of table (from trap table) ADD.L -4(a0,D4*4),a0 ;select routine based on destination depth MOVE.L A0,ModeCase(A6) ;set up jump MOVE dstPix+pixelSize(A6),D7 ;how far to extract to get a pixel worth BFEXTU hilitColor(A6){0:D7},D3 ;and a pixel sized highlight color BFEXTU transColor(A6){0:D7},D6 ;set up a pixel sized background color CLR patRow(A6) ;no pattern BRA GetDst ;go to it @notFastHilite CMP.W #$20,D2 ;non-arithmetic mode? <11> BLO @doOldWay ;yes, skip a bunch of setup <11> AND #$37,D2 ;treat mode MOD $07 + arithmetic bit, hilite bit BCLR #4,D2 ;and clear the hilite bit BNE.S @Hilite if Quicker then cmp.w #3,d4 ;is dest 8, 16 or 32 bits/pixel? <1.7> BAL blt.s @noHilite ;no use indexed arith mode tab cmp.w #4,d4 ;is dest 16 or 32 bits/pixel? <1.7> BAL blt.s @chk8Bit ;determine if Andy wants this one <1.7> BAL else cmp.w #4,d4 ;is dest 16 or 32 bits/pixel? <1.7> BAL blt.s @noHilite ;no use indexed arith mode tab endif move.l rArith32TabPtr,A0 ;point to 32 bit/pixel loops (preserves cc's) bne.s @32ok ;if 16 bit use alternate table move.l rArith16TabPtr,A0 @32ok sub #$20,d2 ;make average tbl entry zero beq.s @chkHalf ;mode is average, check for fast case @notHalf add.l (a0,d2*4),a0 ;get modecase based on d2 move.l a0,modeCase(a6) ;save routine for later bra.s GetPat @chk8Bit if Quicker then ; tst.w hBump(a6) ;right to left? <1.7> BAL ; bmi.s @noHilite ;if so, skip <1.7> BAL lea rArith8Tab,A0 ;point to 8 bit vector table <1.7> BAL MOVE.L INVERTFLAG(A6),D7 ;GET INVERTFLAG INTO D7 bra.s @32ok ; <1.7> BAL endif @chkHalf lea weight(a6),a1 ;point to weights move.w (a1)+,d0 cmp.w (a1)+,d0 ;is opColor gray? bne.s @notHalf cmp.w (a1),d0 bne.s @notHalf addq #1,d0 ;yes, check for gray values of $8000 or $7fff and.w #$fffe,d0 cmp.w #$8000,d0 bne.s @notHalf addq #8,d2 ;use fast 50% blend routine instead bra.s @notHalf @Hilite ADDQ #8,D2 ;if slow hilite, advance to next range @noHilite ADD D2,D2 ;make it a word offset (40 … 4E, 54) SUB #$28,D2 ;(mode AND ($27)) * 2 - jump table offsets (40 - 18) BRA.S @0 ;jump table offsets = 18 … 26, 2C @doOldWay AND #$B,D2 ;TREAT MODE MOD 16, KILL INVERT BIT MOVEQ #3,D0 AND D2,D0 ;GET BOTTOM 2 BITS OF MODE ADD D0,D2 ;MODIFY MODE FOR INDEX CMP #8,D2 ;pattern? BGE.S @checkBigPat ;don’t worry about color src blt loops if so CMP #4,D2 ;xor? BEQ.S @0 ;skip if so BTST #ColorizeInModeCaseBit, XLateFlag(a6) ;colorize? ; tst.w BGnotWhite(A6) ;backcolor white and forecolor black? BEQ.S @0 ;Yes, don’t use color loops ADD #$28,D2 ;use color loops @checkBigPat TST PATROW(A6) ;BIG PATTERN? BEQ.S @0 ;=>NO ADD #8,D2 ;YES, BUMP INDEX @0 LEA RgnBltModeTab,A0 ;POINT TO MODE TABLE MOVE.L 0(A0,D2*2),MODECASE(A6) ;SAVE ROUTINE ADDRESS FOR LATER MOVE.L INVERTFLAG(A6),D7 ;GET INVERTFLAG INTO D7 GetPat ;------------------------------------------------- ; ; SET UP D6 AND D7 FOR PATTERNS ; BTST #3,D1 ;WILL PATTERN BE USED ? BEQ.S USESRC ;NO, USE SOURCE INSTEAD MOVE.L EXPAT(A6),SRCADDR(A6) ;SAVE PTR TO EXPANDED PATTERN AS SRC PTR MOVE PATROW(A6),D1 ;WILL BIG PATTERN BE USED? BEQ.S SMALLPAT ;=>NO, OLD PAT ; NEW PATTERN. SET STARTING VERT POSITION, SET FLAG. MOVEQ #0,D6 ;CLEAR HIGH WORD MOVE PATVMASK(A6),D6 ;GET VERTICAL MASK ADDQ #1,D6 ;CONVERT TO COUNT DIVU PATROW(A6),D6 ;DIVIDE BY ROWSIZE SUBQ #1,D6 ;CONVERT TO ROW MASK AND MINRECT+TOP(A6),D6 ;GET TOP VERT COORD MULU D1,D6 ;GET PATVPOS INTO D6 SWAP D6 ;LEAVE PATVPOS IN HIGH WORD OF D6 ;WE DON'T KNOW PATHPOS FOR D6 YET MOVE PATHMASK(A6),D7 ;SET UP HMASK IN D7 BRA GETDST ;SKIP OVER SRC STUFF ; SET UP (VERT * 4) MOD 64 AS PATTERN SELECTOR ; GET PATTERN SELECTOR INTO D7, FIRST PATTERN INTO D6 SMALLPAT MOVEQ #$F,D7 ;TREAT COORD MOD 16 AND MINRECT+TOP(A6),D7 ;GET TOP VERT COORD MOVE.L ([EXPAT,A6],D7*4),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 SRCRECT(A6),A2 ;POINT TO SRCRECT LEA SRCPIX(A6),A4 ;POINT TO SRCPIX MOVE.L BASEADDR(A4),D0 ;GET SRC BASEADDR CMP.L BASEADDR(A5),D0 ;ARE SRC AND DST SAME BITMAP ? BNE.S SRCOK ;NO, DON'T WORRY ABOUT OVERLAP MOVE TOP(A3),D0 ;GET DST TOP SUB BOUNDS+TOP(A5),D0 ;CONVERT TO GLOBAL MOVE TOP(A2),D1 ;GET SRC TOP SUB BOUNDS+TOP(A4),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(A3),D0 ;GET DST LEFT SUB BOUNDS+LEFT(A5),D0 ;CONVERT TO GLOBAL MOVE LEFT(A2),D1 ;GET SRC LEFT SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL cmp D1,D0 ;DH := DSTLEFT-SRCLEFT BLE.S SRCOK ;IF DH <= 0, WE'RE FINE MOVE right(A2),D1 ;GET SRC right SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL cmp d1,d0 ;is the srcRight < dstLeft ? bge.s srcOK ;yes, they don't overlap! 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(A3),D6 ;GET DST LEFT LOCAL COORDS SUB BOUNDS+LEFT(A5),D6 ;CONVERT TO GLOBAL EXT.L D6 ;MAKE LONG FOR BIG PIXELS LSL.L D4,D6 ;CONVERT DST PIXELS TO BITS MOVE LEFT(A2),D1 ;GET SRC LEFT LOCAL COORDS SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL EXT.L D1 ;MAKE LONG FOR BIG PIXELS LSL.L D4,D1 ;CONVERT SRC PIXELS TO BITS SUB.L D1,D6 ;CALC DELTA HORIZ BITS MOVEQ #$1F,D0 ;NEED DELTA HORIZ MOD 32 AND.L D0,D6 ;MOD 32 FOR SHIFTCNT NEG.L D6 ;CHANGE SHIFT TO OFFSET ;leave d6 as neg(# bits to shift right) ;------------------------------------ ; ; CALC STARTING SRCADDR ; MOVE FIRSTV(A6),D0 ;GET FIRST DST VERTICAL SUB TOP(A3),D0 ;SUBTRACT DSTRECT TOP ADD TOP(A2),D0 ;ADD SRCRECT TOP SUB BOUNDS+TOP(A4),D0 ;CONVERT SRCV TO GLOBAL MOVE ROWBYTES(A4),D1 ;GET SRC ROWBYTES AND #nuRBMask,D1 ;AND MASK OFF FLAG BITS MULS D1,D0 ;MULT BY SRC ROWBYTES BAL 02Dec88 MOVE.L BASEADDR(A4),A0 ;GET START OF BITMAP ADD.L D0,A0 ;ADD OFFSET TO BASEADDR MOVE MINRECT+LEFT(A6),D0 ;GET DST LEFT SUB LEFT(A3),D0 ;CONVERT FROM DST COORDS ADD LEFT(A2),D0 ;TO SRC COORDS SUB BOUNDS+LEFT(A4),D0 ;CONVERT TO GLOBAL SRC EXT.L D0 ;MAKE LONG FOR BIG PIXELS LSL.L D4,D0 ;CONVERT SRC PIXELS TO BITS SUB.L D6,D0 ;ADD SHIFTCNT ASR.L #5,D0 ;CONVERT BITS TO LONGS LSL.L #2,D0 ;CONVERT LONGS TO BYTES ADD.L 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(A5),D0 ;CONVERT TO GLOBAL MOVE ROWBYTES(A5),D1 ;GET DST ROWBYTES AND #nuRBMask,D1 ;AND MASK OFF FLAG BITS MULS D1,D0 ;MULT BY ROWBYTES BAL 02Dec88 MOVE.L BASEADDR(A5),A0 ;GET START OF BITMAP ADD.L D0,A0 ;ADD VERTICAL OFFSET MOVE MINRECT+LEFT(A6),D0 ;GET DST LEFT SUB BOUNDS+LEFT(A5),D0 ;CONVERT TO GLOBAL EXT.L D0 ;MAKE LONG FOR BIG PIXELS LSL.L D4,D0 ;CONVERT DST PIXELS TO BITS LSR.L #5,D0 ;CONVERT BITS TO LONGS LSL.L #2,D0 ;CONVERT LONGS TO BYTES MOVE D0,D1 ;SAVE GLOBAL DSTLEFT ADD.L A0,D0 ;ADD HORIZ OFFSET MOVE.L D0,DSTADDR(A6) ;SAVE AS DSTADDR ;------------------------------------ ; ; SET UP D6 FOR BIG PATTERNS ; TST PATROW(A6) ;DOING BIG PATTERN? BEQ.S NOTBIGPAT ;=>NO AND D7,D1 ;MASK HORIZ OFFSET INTO PATTERN MOVE D1,PATHPOS(A6) ;SAVE HORIZONTAL OFFSET MOVE D1,D6 ;SAVE PATHPOS IN D6 SWAP D6 ;GET PATVPOS IN LOW WORD NOTBIGPAT ;------------------------------------------------------------------------ ; ; ADJUST SRCADDR,DSTADDR,RGNADDR IF WE ARE BUMPING BACKWARDS FROM RIGHT ; MOVE locMode(A6),D2 MOVE.L hilitColor(A6),D4 ;set up hilite color CMP #$10,D2 ;if fast hilite, bump left -> right is fine, BEQ.S skipBump ;& D3 is already set up to background pixel tst.l runBuf(a6) ;are we run clipping? <1.5> BAL bne.s HBUMPOK ;if so, do new way ; the following is only used by old arithmetic modes ; which don't work right to left anyway TST HBUMP(A6) ;BUMPING BACKWARD ? BPL.S HBUMPOK ;NO, CONTINUE MOVE BUFSIZE(A6),D0 ;GET BUFFER SIZE EXT.L D0 ;CLEAR HI WORD LSL.L #2,D0 ;QUAD FOR # BYTES ADD.L D0,DSTADDR(A6) ;ADJUST DSTADDR ADD.L D0,RGNADDR(A6) ;ADJUST RGNADDR ADD.L D0,SRCADDR(A6) ;ADJUST SRCADDR HBUMPOK MOVE HBUMP(A6),D3 ;GET HBUMP MOVE.L FCOLOR(A6),D4 ;GET FG COLOR MOVE.L BColor(A6),D5 ;GET BK COLOR skipBump MOVE FIRSTV(A6),VERT(A6) ;INIT CURRENT VERTICAL ;set up any needed registers for new modes BTST #5,D2 ;a new arithmetic mode? BEQ @skipArithmetic MOVEQ #0,D1 ;zero high word MOVE dstPix+pixelSize(A6),D1 ;get number of bits in a pixel MOVE.L transColor(A6),D5 ;get background color for hilite/transparent BTST #3,D2 ;is the pattern bit set? BEQ.S @newSource ;if not, must be source TST patRow(A6) BEQ.S @smallPattern ;if no pat row, pattern is small ; big pattern case MOVE.B #1,endSwitch(A6) ;note that this is a big pattern MOVE D6,patPos(A6) ;set up large pattern vertical offset MOVE.L srcAddr(A6),A0 ;bump pattern pointer as well ADD D6,A0 MOVE.L A0,srcAddr(A6) CLR D6 ;clear high word for bit operations SWAP D6 ASL.L #3,D6 ;scale from bytes to bits for bit operation offset MOVE.L D6,patOffset(A6) ;set up initial horizontal offset ; need to scale patHMask from longs to pixels MOVE D1,D3 ;get number of bits in a pixel SUBQ #1,D3 ;make into a mask NOT D3 ;turn on bits equal to & greater than pixelSize MOVE patRow(A6),D0 ;get pattern row size ASL #3,D0 ;convert from bytes to bits SUBQ #1,D0 ;make it a mask AND D3,D0 ;force pixel alignment MOVE D0,patHMask(A6) BRA.S @skipMaskSetup ; small pattern case @smallPattern CLR.B endSwitch(A6) ;note that this is a small pattern LEA ([EXPAT,A6],D7*4),A3 ;GET FIRST PATTERN DATA MOVE.L A3,srcAddr(A6) MOVE D7,patPos(A6) ;save initial offset as well MOVEQ #0,D6 MOVE.L D6,patOffset(A6) MOVE #$001F,patHMask(A6) ;set up patHMask for old patterns (must fit into a long) BRA.S @skipMaskSetup ; source case @newSource ST endSwitch(A6) ;note that this is a source (set negative) MOVE.L D6,patOffset(A6) ;save initial offset for next scan line MOVE #-1,patHMask(A6) ;do not restrict source range if mode is source @skipMaskSetup cmp.w #16,d1 ;is dst 16 or 32 bits/pixel? <05Mar89 BAL> blt.s @notDirect ;no, leave patOffset,patHMask in bits asr.l #3,d6 ;yes, make patOffset,patHMask into bytes move.l d6,patOffset(a6) move.w patHMask(a6),d0 ; <10Jan89 BAL> asr.w #3,d0 move.w d0,patHMask(a6) ; <10Jan89 BAL> @notDirect MOVE D1,D7 ;set up bits per pixel depth AND #$37,D2 ;ignore the pattern info CMP #$24,D2 ;skip this part if mode is transparent BEQ.S @skipColorTable MOVE invSize(A6),D5 ;set up inverse table resolution in a register @skipColorTable CMP #$32,D2 ;hilite? BNE.S @notHilite BFEXTU hilitColor(A6){0:D7},D5 ;set up a pixel of the hilite color @notHilite ; D4 first destination/mask pixel position MOVEQ #5,D4 ;shift amt for 32 bits SUB.W DSTSHIFT(A6),D4 ;get 5-DSTSHIFT MOVEQ #1,D0 ; LSL D4,D0 ;compute 32/pixelsize MOVE D0,pixInLong1(A6) MOVE D0,D2 ;keep a copy around MOVEQ #0,D4 ;assume destination offset is 0 MOVE.L D7,D3 ;assume bump is positive MOVEQ #32,D1 ;positive long bump for transparent TST hBump(A6) ;bumping postive or negative? BPL.S @bumpOK NEG.L D3 ;make pixel bump negative NEG D1 ;make long bump negative MOVEQ #32,D4 SUB D0,D4 ;D4 set to first destination pixel position ADD.L D4,D6 ;D6 set to first source pixel position @bumpOK MOVE D4,destPixOffset(A6) MOVE D1,longBump(A6) ;set up long bump for transparent MOVE bufSize(A6),D0 ADDQ #1,D0 ;make it 1 based MULU D2,D0 ;scale up by pixels in a long SUBQ #1,D0 ;make it zero based again for DBRA MOVE D0,bufSize(A6) @skipArithmetic ;---------------------------------------------------------- ; ; Jump into 32 bit addressing mode for blitting. @@@@ BAL 09Apr88 ; moveq #true32b,d0 ;switch to 32 bit addressing @@@@ BAL 09Apr88 _rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2) move.b d0,MMUsave(a6) ;save previous state for later @@@@ BAL 09Apr88 ;------------------------------------------------------- ; ; MAKE REGION BUFFER CURRENT FOR THIS VERTICAL. ; THEN SET UP AND DRAW CURRENT SCANLINE. ; tst.l runBuf(a6) ;are we run clipping? <1.5> BAL bne.s FirstRunMask ;if so, do new way <1.5> BAL NXTMASK JSR ([SEEKMASK,A6]) ;MAKE MASK BUFFER CURRENT MOVE.L SRCADDR(A6),A3 ;INIT SRCPTR MOVE.L DSTADDR(A6),A5 ;INIT DSTPTR FOR ROW MOVE.L RGNADDR(A6),A4 ;INIT RGNPTR FOR ROW MOVE BUFSIZE(A6),D2 ;INIT COUNT OF LONGS or pixels MOVE.L MODECASE(A6),A2 ;GET MODE CASE JUMP JMP (A2) ;TAKE MODE JUMP FirstRunMask MOVE.L DSTADDR(A6),A5 ;INIT DSTPTR MOVE.L runBuf(A6),A4 ;INIT runBuf ptr move.w hBump(a6),RUNBUMP(a6) ;set transfer direction for seekmask btst #5,locMode+1(A6) ;arithmetic transfer mode? beq.s @notArith ;no, registers are ok move.w hBump(a6),a4 ;set up a4, and d4 for arith loops move.w patHMask(a6),d4 @notArith tst DstRow(a6) ;top to bottom transfer? bpl.s topDown ;yes, skip scan count hack addq #1,vert(a6) ;begin one below the bottom JSR ([SEEKMASK,A6]) ;preseek past bottom subq #1,vert(a6) ;reposition to last scan bra.s topDown ;continue nextMask move d0,vert(a6) ;update vert MOVE.L a3,SRCADDR(A6) ;update SRCPTR topDown JSR ([SEEKMASK,A6]) ;MAKE MASK BUFFER CURRENT move d2,d1 ;get scan count in d1 JSR ([RUNRTN,A6]) ;MAKE RUN BUFFER CURRENT move.w vert(a6),d0 ;reload vert position move.l DstRow(a6),d2 ;set up dest rowbytes MOVE.L SRCADDR(A6),A3 ;reload SRCPTR 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 NEXTBIGPAT MOVE PATHPOS(A6),D6 ;GET HORIZONTAL POSITION SWAP D6 ;GET VERT POSITION IN PATTERN ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ;LEAVE PATVPOS IN D6 BRA.S BUMPV ;=>CONTINUE WITH NEXT ROW NEXTPAT ADD #1,D7 ;BUMP PATTERN SELECTOR AND #$F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L ([EXPAT,A6],D7*4),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 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. JUST RETURN ; DONE MOVE.L SAVESTK2(A6),SP ;RESTORE STACK POINTER RTS ;AND RETURN TO STRETCHBITS ;---------------------------------------------------------------; ; ; Standard 1-8 bit Arithmetic transfer mode scan line loop ; for classic region masking only. ; NxtNewSrc MOVE destPixOffset(A6),D4 ;set up destination horizontal offset MOVE.L patOffset(A6),D6 ;set up source horizontal offset TST.B endSwitch(A6) BEQ.S @nxtNewPat BMI.S NextSrc ; nxtNewBigPat moveq #0,d0 ;patPos should be a long MOVE patPos(A6),D0 ;GET VERT POSITION IN PATTERN SUB.l D0,A3 ;GET BACK PAT BASE ADD PATROW(A6),D0 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D0 ;AND MASK WITHIN PATTERN ADD.l D0,A3 ;BUMP TO PROPER VERT MOVE D0,patPos(A6) ;SAVE VERTICAL POSITION BRA.S @saveSrcAddr @nxtNewPat MOVE patPos(A6),D0 ADD #1,D0 ;BUMP PATTERN SELECTOR AND #$F,D0 ;MOD 16 FOR 16 LONG REPEAT LEA ([EXPAT,A6],D0*4),A3 ;GET PATTERN FOR NEXT ROW MOVE D0,patPos(A6) @saveSrcAddr MOVE.L A3,srcAddr(A6) ;point source address to it BRA.S BumpV ALIGN Alignment ;---------------------------------------------------------------; ; ; Run masked Arithmetic transfer mode scan line loop ; for 32 bit pixels only. ; NxtNewSrc32b move.l a2,d1 ;restore scanCount NxtNewSrc32 MOVE.L patOffset(A6),D6 ;set up source horizontal offset TST.B endSwitch(A6) BEQ.S nxtNewPat32 BMI.S NextSrc32 ;nxtNewBigPat32 moveq #0,d0 ;patPos should be a long MOVE patPos(A6),D0 ;GET VERT POSITION IN PATTERN SUB.l D0,A3 ;GET BACK PAT BASE ADD PATROW(A6),D0 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D0 ;AND MASK WITHIN PATTERN ADD.l D0,A3 ;BUMP TO PROPER VERT MOVE D0,patPos(A6) ;SAVE VERTICAL POSITION BRA.S doItAgain32 nxtNewPat32 MOVE patPos(A6),D0 ADD #1,D0 ;BUMP PATTERN SELECTOR AND #$F,D0 ;MOD 16 FOR 16 LONG REPEAT LEA ([EXPAT,A6],D0*4),A3 ;GET PATTERN FOR NEXT ROW MOVE D0,patPos(A6) bra.s doItAgain32 NextSrc32 add.l srcRow(a6),a3 ;BUMP src TO NEXT ROW doItAgain32 move.l dstAddr(a6),a5 ;reload dst ptr add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW move.l a5,dstAddr(a6) ;save dst ptr move.w vert(a6),d0 ;reload vert position ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ble.s nextMask move.w d0,vert(a6) ;save vert position MOVE.L MODECASE(A6),A2 ;GET MODE CASE JUMP JMP (A2) ;TAKE MODE JUMP ;---------------------------------------------------------------; ; ; ; INTERFACE TO EACH OF THE RGNBLT SCANLINE LOOPS: ; ; ; ; REGISTERS: A0: D0: ; ; A1: D1: ; ; A2: D2: LONGCNT ; ; A3: SRCPTR/PATPTR D3: HBUMP ; ; A4: MASKPTR D4: FCOLOR ; ; A5: DSTPTR D5: BCOLOR ; ; A6: D6: SHIFTCNT OR PATTERN ; ; OR INDEX INTO PATTERN ; ; A7: D7: INVERTFLAG OR PAT-SEL ; ; ; ;---------------------------------------------------------------; IF 0 THEN MODETAB DC.W MASK0-MODETAB ;0 DC.W MASK1-MODETAB ;2 DC.W MASK2-MODETAB ;4 DC.W MASK3-MODETAB ;6 DC.W MASK8-MODETAB ;8 DC.W MASK9-MODETAB ;A DC.W MASK10-MODETAB ;C DC.W MASK11-MODETAB ;E DC.W XMASK8-MODETAB ;10 DC.W XMASK9-MODETAB ;12 DC.W XMASK10-MODETAB ;14 DC.W XMASK11-MODETAB ;16 DC.W Avg-ModeTab ;18 AVG(SRC, DST, WEIGHT) --> DST DC.W AddPin-ModeTab ;1A SRC + DST --> DST (pin to max) DC.W AddOver-ModeTab ;1C SRC + DST --> DST (no pin) DC.W SubPin-ModeTab ;1E DST - SRC --> DST (pin to min) DC.W Transparent-ModeTab ;20 SRC less bg --> DST DC.W Max-ModeTab ;22 MAX(SRC, DST) --> DST DC.W SubOver-ModeTab ;24 DST - SRC --> DST (no pin) DC.W Min-ModeTab ;26 MIN(SRC, DST) --> DST DC.W cMask0-ModeTab ;28 DC.W cMask1-ModeTab ;2A DC.W slowHilite-ModeTab ;2C (src, pat as mask) hilite color <--> background color DC.W cMask3-ModeTab ;2E ENDIF ALIGN 4 if Quicker then IMPORT rAddOver8 IMPORT rSubOver8 IMPORT rAddPin8 IMPORT rSubPin8 IMPORT rMax8 IMPORT rMin8 IMPORT rAvg8,rTransparent8 rArith8Tab DC.L rAvg8-rArith8Tab ;18 AVG(SRC, DST, WEIGHT) --> DST DC.L rAddPin8-rArith8Tab ;1A SRC + DST --> DST (pin to max) DC.L rAddOver8-rArith8Tab ;1C SRC + DST --> DST (no pin) DC.L rSubPin8-rArith8Tab ;1E DST - SRC --> DST (pin to min) DC.L rTransparent8-rArith8Tab ;20 SRC less bg --> DST DC.L rMax8-rArith8Tab ;22 MAX(SRC, DST) --> DST DC.L rSubOver8-rArith8Tab ;24 DST - SRC --> DST (no pin) DC.L rMin8-rArith8Tab ;26 MIN(SRC, DST) --> DST DC.L rAvg8-rArith8Tab ;50% case endif rArith16Tab DC.L rAvg16-rArith16Tab ;18 AVG(SRC, DST, WEIGHT) --> DST DC.L rAddPin16-rArith16Tab ;1A SRC + DST --> DST (pin to max) DC.L rAddOver16-rArith16Tab ;1C SRC + DST --> DST (no pin) DC.L rSubPin16-rArith16Tab ;1E DST - SRC --> DST (pin to min) DC.L rTransparent16-rArith16Tab ;20 SRC less bg --> DST DC.L rMax16-rArith16Tab ;22 MAX(SRC, DST) --> DST DC.L rSubOver16-rArith16Tab ;24 DST - SRC --> DST (no pin) DC.L rMin16-rArith16Tab ;26 MIN(SRC, DST) --> DST DC.L rAvg16Half-rArith16Tab ;28 rArith32Tab DC.L rAvg32-rArith32Tab ;18 AVG(SRC, DST, WEIGHT) --> DST DC.L rAddPin32-rArith32Tab ;1A SRC + DST --> DST (pin to max) DC.L rAddOver32-rArith32Tab ;1C SRC + DST --> DST (no pin) DC.L rSubPin32-rArith32Tab ;1E DST - SRC --> DST (pin to min) DC.L rTransparent32-rArith32Tab ;20 SRC less bg --> DST DC.L rMax32-rArith32Tab ;22 MAX(SRC, DST) --> DST DC.L rSubOver32-rArith32Tab ;24 DST - SRC --> DST (no pin) DC.L rMin32-rArith32Tab ;26 MIN(SRC, DST) --> DST DC.L rAvg32Half-rArith32Tab ;28 rHiliteTab ; (1-bit hilite converted to Xor) DC.L rHilite-rHiliteTab ; 2-bit DC.L rHilite-rHiliteTab ; 4-bit DC.L rHilite-rHiliteTab ; 8-bit DC.L rHilite-rHiliteTab ;16-bit DC.L rHilite32-rHiliteTab ;32-bit ALIGN Alignment ;---------------------------------------------------------------; ; ; ; INTERFACE TO EACH OF THE RUN MASKED SCANLINE LOOPS: ; ; ; ; a0 = tmpsrc d0 = vert ; a1 = tmpmask d1 = scanCount ; a2 = tmpdst d2 = dstRow/left shift cnt ; a3 = srcPtr/patPtr d3 = run cnt/hBump/scratch ; a4 = runPtr d4 = fColor/scratch ; a5 = dstPtr d5 = bColor/scratch ; a6 = locals d6 = pattern/pat index/rgt shift cnt ; a7 = d7 = pat select/INVERTFLAG ;------------------------------------------------------- ; ; move.l (a0)+,d4 ; 1 read cycle ; ; lsl.l d6,d5 ; 3, 6, 6 ; move.l d4,d7 ; 0, 2, 3 ; lsr.l d2,d7 ; 3, 6, 6 ; or.l d5,d7 ; 0, 2, 3 ; move.l d7,(a2)+ ; move.l d4,d5 ; 0, 2, 3 ; --------------- ; ; 6, 18, 21 + 1 read cycle ; ; bfextu (A3){D6:0},D0 ; 18, 18, 18 + 2 read cycles ; ;------------------------------------------------------- ; ; MODE 0 OR 4: SRC --> DST ; rMASK0 tst.l d7 ;must src be inverted? bne.s @slow ;yes, go slow tst.w d3 ;is hBump negative bmi.s @slow ;yes, go slow neg.l d6 ;make d6 # bits to shift right move d6,d4 ;get shift cnt and #7,d4 ;is it a multiple of 8? bne.s @med ;no, can't go fast @fast asr.w #3,d6 ;compute byte shift sub.w d6,a3 ;adjust src ptr by byte shift lea rSrcCopyFast,a2 @go move.l a2,modeCase(a6) ;go there from now on jmp (a2) @med moveq #32,d3 ;compute left shift from right shift cnt sub d6,d3 lea rSrcCopyLtoR,a2 bra.s @go @slow lea rSrcCopySlow,a2 bra.s @go ALIGN Alignment ;------------------------------------------------------- ;rSrcCopySlow ; Run masked src copy mode where: ; ; HBump may be negative ; Src may be inverted ; nxtScan0 add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count ble.s nextMask rSrcCopySlow move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s nxtScan0 ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount add.w d2,a0 ;bump srcptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src move.l (a1)+,d5 ;fetch mask and.l d5,d4 ;mask src not.l d5 and.l (a2),d5 or.l d5,d4 move.l d4,(a2) ;write back result add d3,a2 ;%%%bump dst DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src move.l d4,(a2) add d3,a2 ;%%%bump dst DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ;rSrcCopyLtoR ; ; Run masked src copy mode where: ; ; HBump is positive (+4) ; ShiftCnt is not a multiple of 8 ; Src is not inverted ; nxtScan1 add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count ble.s nextMask rSrcCopyLtoR move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s nxtScan1 ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount add.w d2,a0 ;bump srcptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @fblit ;no mask, so go fast @fmask move.l -4(a0),d5 ;fill pipeline with prefetch @mask move.l (a0)+,d4 ; 1 read cycle lsl.l d3,d5 ; 3, 6, 6 move.l d4,d7 ; 0, 2, 3 lsr.l d6,d7 ; 3, 6, 6 or.l d5,d7 ; 0, 2, 3 move.l (a1)+,d5 ;fetch mask and.l d5,d7 not.l d5 and.l (a2),d5 or.l d5,d7 move.l d7,(a2)+ move.l d4,d5 ; 0, 2, 3 DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @fblit move.l -4(a0),d5 ;fill pipeline with prefetch @blit move.l (a0)+,d4 ; 1 read cycle lsl.l d3,d5 ; 3, 6, 6 move.l d4,d7 ; 0, 2, 3 lsr.l d6,d7 ; 3, 6, 6 or.l d5,d7 ; 0, 2, 3 move.l d7,(a2)+ move.l d4,d5 ; 0, 2, 3 DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ;rSrcCopyFast ; ; Run masked src copy mode where: ; ; HBump is positive (+4) ; ShiftCnt is a multiple of 8 (e.g. bit depth >= 8) ; Src is not inverted ; nxtScan2 add.l d2,a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count ble.s nextMask rSrcCopyFast move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s nxtScan2 ;if high bit set then done with scan add.w d3,a2 ;bump destptr by skip amount add.w d3,a0 ;bump srcptr by skip amount swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask move.l (a0)+,d4 ; 1-2 read cycles move.l (a1)+,d5 ;fetch mask and.l d5,d4 not.l d5 and.l (a2),d5 or.l d4,d5 move.l d5,(a2)+ DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ; Here's the unwound loop to blast the # of longwords in D3 + 1 out. ; (courtesy of Gary) @blit MOVEQ #$F,D4 AND.W D3,D4 ;partial block size NEG.W D4 ;back up from end LSR #4,D3 ;cnt of 16 long blocks JMP (@Start,D4.W*2) ;blast them out @DoSixteen MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ MOVE.L (a0)+,(a2)+ @Start MOVE.L (a0)+,(a2)+ DBRA D3,@DoSixteen BRA.S @inst ALIGN Alignment rSrcOr ;------------------------------------------------------- ; ; MODE 1 OR 5: SRC OR DST --> DST (Common for Text) ; ;------------------------------------------------------- ;rSrcOr ; Run masked src OR mode where: ; ; HBump may be negative ; Src may be inverted ; @nxtScan add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count ble.s nextMask @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount add.w d2,a0 ;bump srcptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src and.l (a1)+,d4 ;fetch mask and mask src or.l d4,(a2) ;OR result into dst add d3,a2 ;%%%bump dst DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src or.l d4,(a2) add d3,a2 ;%%%bump dst DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rMASK1 EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 2 OR 6: SRC XOR DST --> DST ; ;------------------------------------------------------- ;rSrcXOr ; Run masked src XOR mode where: ; ; HBump may be negative ; Src may be inverted ; @nxtScan add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count ble.s nextMask ;rMASK2 @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount add.w d2,a0 ;bump srcptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src and.l (a1)+,d4 ;fetch mask and mask src eor.l d4,(a2) ;XOR result into dst add d3,a2 ;%%%bump dst DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src eor.l d4,(a2) add d3,a2 ;%%%bump dst DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rMASK2 EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 3 OR 7: SRC BIC DST --> DST ; ;------------------------------------------------------- ;rSrcBIC ; Run masked src BIC mode where: ; ; HBump may be negative ; Src may be inverted ; @nxtScan add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count ble.s nextMask ;rMASK3 @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount add.w d2,a0 ;bump srcptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src and.l (a1)+,d4 ;fetch mask and mask src not.l d4 ;invert for BIC and.l d4,(a2) ;apply result into dst add d3,a2 ;%%%bump dst DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit BFEXTU (A0){D6:0},D4 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d4 ;conditionally invert src not.l d4 ;invert for BIC and.l d4,(a2) add d3,a2 ;%%%bump dst DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rMASK3 EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 0 OR 4: SRC --> DST (fg ≠ black or bg ≠ white) ; ; <18Oct90 SMC> <9> ; Made register usage more efficient and used a ; faster, smaller colorizing method. ; ;------------------------------------------------------- ;rcSrcCopy ; Run masked colorizing src COPY mode where: ; ; HBump may be negative ; Src may be inverted ; rcMASK0 move.w hBump(a6),a4 ;get hbump in a4 bra.s @runs ;go use run mask @nxtScan EOR.L D5,D4 ;unmunge bkcolor into fgcolor <9> add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW MOVE vert(A6),D0 ; <9> ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count <9> ble.s nextMask ; <9> MOVE D0,vert(A6) ; <9> @runs move.l a5,a2 ;init tmp dst ptr move.l RunBuf(a6),a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr EOR.L D5,D4 ;munge bkcolor into fgcolor <9> @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount add.w d2,a0 ;bump srcptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask BFEXTU (A0){D6:0},D3 ;get an aligned long of src add a4,a0 ;%%%bump src right or left eor.l d7,d3 ;conditionally invert src AND.L D4,D3 ;apply munged fgcolor to src <9> EOR.L D5,D3 ;apply bkcolor to src <9> MOVE.L (A2),D0 ;get dst <9> EOR.L D0,D3 ;apply it to src <9> AND.L (A1)+,D3 ;make it <9> EOR.L D0,D3 ;reapply dst to src <9> MOVE.L D3,(A2) ;move result to dst <9> add a4,a2 ;%%%bump dst DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit BFEXTU (A0){D6:0},D3 ;get an aligned long of src add a4,a0 ;%%%bump src right or left eor.l d7,d3 ;conditionally invert src AND.L D4,D3 ;apply munged fgcolor to src <9> EOR.L D5,D3 ;apply bkcolor to src <9> MOVE.L D3,(A2) ;put colorized src to dst add a4,a2 ;%%%bump dst DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment rcSrcOr ;------------------------------------------------------- ; ; MODE 1 OR 5: SRC OR DST --> DST (fg ≠ black) ; ; <18Oct90 SMC> <9> ; Eliminated one NuBus read and one NuBus write per long by ; freeing up an under-utilized register and, as a result, ; improving performance and shrinking code size. ; ;------------------------------------------------------- ;rcSrcOr ; Run masked colorizing src OR mode where: ; ; HBump may be negative ; Src may be inverted ; @nxtScan add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW add.l srcRow(a6),a3 ;BUMP DST TO NEXT ROW MOVE vert(A6),D0 ;get vertical position <9> ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? beq DONE ;YES, BAIL subq #1,d1 ;decrement scan count ble.s nextMask MOVE D0,vert(A6) ;save new vertical position <9> ;rcMASK1 @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l a3,a0 ;init tmp src ptr @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount add.w d2,a0 ;bump srcptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask BFEXTU (A0){D6:0},D5 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d5 ;conditionally invert src and.l (a1)+,d5 ;fetch mask and mask src NOT.L D5 ;make source a punch MOVE.L (A2),D0 ;get dst <9> EOR.L D4,D0 ;combine src and forecolor <9> AND.L D5,D0 ;mask with source <9> EOR.L D4,D0 ;reapply forecolor to src <9> MOVE.L D0,(A2) ;move the result to dst <9> add d3,a2 ;%%%bump dst DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit BFEXTU (A0){D6:0},D5 ;get an aligned long of src add d3,a0 ;%%%bump src right or left eor.l d7,d5 ;conditionally invert src NOT.L D5 ;make source a punch MOVE.L (A2),D0 ;get dst <9> EOR.L D4,D0 ;combine src and forecolor <9> AND.L D5,D0 ;mask with source <9> EOR.L D4,D0 ;reapply forecolor to src <9> MOVE.L D0,(A2) ;move the result to dst <9> add d3,a2 ;%%%bump dst DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rcMASK1 EQU @runs ;------------------------------------------------------- ; ; MODE 3 OR 7: SRC BIC DST --> DST (bg ≠ white) ; ; <18Oct90 SMC> <9> ; Folded BIC loop into OR loop by making forecolor equal backcolor. ; ;------------------------------------------------------- ;rcSrcBIC ; Run masked colorizing src BIC mode where: ; ; HBump may be negative ; Src may be inverted ; rcMASK3 MOVE.L D5,D4 ;make bkcolor the fgcolor <9> LEA rcMASK1,A2 ;learn it <9> MOVE.L A2,modeCase(A6) ;know it <9> JMP (A2) ;live it <9> ;------------------------------------------------------- ; ; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES) ; ;------------------------------------------------------- ; a0 = tmpsrc d0 = vert ; a1 = tmpmask d1 = scanCount ; a2 = tmpdst d2 = dstRow ; a3 = srcPtr/patPtr d3 = run cnt/hBump/scratch ; a4 = runPtr d4 = fColor/scratch ; a5 = dstPtr d5 = bColor/scratch ; a6 = locals d6 = pattern/pat index/shift cnt ; a7 = d7 = pat select/invert ;------------------------------------------------------- ; <10> Start of alpha changes block from QDciPatchROM.a stb rMASK8 LEA rMASK8G,A2 ;get address of normal routine TST.B alphaMode(A6) ;drawing in alpha mode? BEQ.S @1 ;no, use normal loop LEA rMASK8A,A2 ;get address of alpha loop @1: MOVE.L A2,modeCase(A6) ;save proc address JMP (A2) ;go there now ALIGN Alignment @nxtScan ADDQ #1,D7 ;BUMP PATTERN SELECTOR AND #$F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L (a3,D7*4),D6 ;GET PATTERN FOR NEXT ROW add.l d2,a5 ;BUMP DST TO NEXT ROW MOVE vert(A6),D0 ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask MOVE D0,vert(A6) ;rMASK8A @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer MOVE.L alphaMask(A6),D5 ;get alpha mask @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d3,a2 ;bump destptr by skip amount swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask MOVE.L D6,D0 ;GET PATTERN DATA MOVE.L (A2),D4 ;GET DST EOR.L D4,D0 ;COMBINE DST WITH PATTERN AND.L (A1)+,D0 ;APPLY REGION MASK AND.L D5,D0 ;APPLY ALPHA MASK EOR.L D4,D0 ;REAPPLY DST TO PATTERN MOVE.L D0,(A2)+ ;PUT RESULT TO DST DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit MOVE.L D6,D0 ;GET PATTERN DATA MOVE.L (A2),D4 ;GET DST EOR.L D4,D0 ;COMBINE DST WITH PATTERN AND.L D5,D0 ;APPLY ALPHA MASK EOR.L D4,D0 ;REAPPLY DST TO PATTERN MOVE.L D0,(A2)+ ;PUT RESULT TO DST DBRA D3,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rMASK8A equ @runs ; <10> End of alpha changes block ALIGN Alignment ;------------------------------------------------------- ; ; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES) ; ;------------------------------------------------------- ; a0 = tmpsrc d0 = vert ; a1 = tmpmask d1 = scanCount ; a2 = tmpdst d2 = dstRow ; a3 = srcPtr/patPtr d3 = run cnt/hBump/scratch ; a4 = runPtr d4 = fColor/scratch ; a5 = dstPtr d5 = bColor/scratch ; a6 = locals d6 = pattern/pat index/shift cnt ; a7 = d7 = pat select/invert ;------------------------------------------------------- @nxtScan ADDQ #1,D7 ;BUMP PATTERN SELECTOR AND #$F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L (a3,D7*4),D6 ;GET PATTERN FOR NEXT ROW add.l d2,a5 ;BUMP DST TO NEXT ROW ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask ;rMASK8 @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d3,a2 ;bump destptr by skip amount swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask MOVE.L D6,D5 ;GET PATTERN DATA MOVE.L (A1)+,D4 ;GET MASK AND.L D4,D5 ;MASK PATTERN DATA NOT.L D4 ;MAKE NOTMASK AND.L (A2),D4 ;GET DST DATA OR.L D4,D5 ;MERGE WITH PAT DATA MOVE.L D5,(A2)+ ;PUT RESULT TO DST DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ; Here's the unwound loop to blast the # of longwords in D3 + 1 out. ; (courtesy of Gary) @blit MOVEQ #$F,D4 AND.W D3,D4 ;partial block size NEG.W D4 ;back up from end LSR #4,D3 ;cnt of 16 long blocks JMP (@Start,D4.W*2) ;blast them out @DoSixteen MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ MOVE.L D6,(a2)+ @Start MOVE.L D6,(a2)+ DBRA D3,@DoSixteen BRA.S @inst rMASK8G EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 9 OR 13: PATTERN OR DST --> DST ; @nxtScan ADDQ #1,D7 ;BUMP PATTERN SELECTOR AND #$F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L (a3,D7*4),D6 ;GET PATTERN FOR NEXT ROW add.l dstRow(a6),a5 ;BUMP DST TO NEXT ROW ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask ;rMASK9 @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer move.l fcolor(a6),d2 ;load fgColor (bkColor) @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d3,a2 ;bump destptr by skip amount swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit1 ;no mask, so go fast @mask MOVE.L D6,D5 ;GET PATTERN DATA AND.L (A1)+,D5 ;MASK PATTERN DATA move.l d5,d4 ;make a copy not.l d4 ;make into mask and.l (a2),d4 ;punch hole in dest and.l d2,d5 ;apply fgColor (bkColor) or.l d5,d4 ;merge in src move.l d4,(A2)+ ;put to dst DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit1 move.l d6,d5 ;make a copy of pattern not.l d5 ;use as mask and.l d2,d6 ;apply fgColor (bkColor) - goodbye pattern @blit move.l d5,d4 ;make a copy and.l (a2),d4 ;punch hole in dest or.l d6,d4 ;merge in src move.l d4,(A2)+ ;put to dst DBRA D3,@blit ;LOOP ALL LONGS THIS ROW move.l d5,d6 ;get not pattern not.l d6 ;restore pattern BRA.s @inst ;LOOP BACK FOR more runs rMASK9 EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 10 OR 14: PATTERN XOR DST --> DST (INVERTING AREAS, XOR LINES) ; @nxtScan ADDQ #1,D7 ;BUMP PATTERN SELECTOR AND #$F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L (a3,D7*4),D6 ;GET PATTERN FOR NEXT ROW add.l d2,a5 ;BUMP DST TO NEXT ROW ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask ;rMASK10 @runs move.l a5,a2 ;init tmp dst ptr move.l a4,a1 ;point to run encoded mask buffer @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d3,a2 ;bump destptr by skip amount swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask MOVE.L D6,D5 ;GET PATTERN DATA AND.L (A1)+,D5 ;MASK PATTERN DATA EOR.L D5,(A2)+ ;XOR RESULT INTO DST DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit ; EOR.L D6,(A2)+ ;XOR RESULT INTO DST ; DBRA D3,@blit ;LOOP ALL LONGS THIS ROW ; BRA.s @inst ;LOOP BACK FOR more runs MOVEQ #$F,D4 AND.W D3,D4 ;partial block size NEG.W D4 ;back up from end LSR #4,D3 ;cnt of 16 long blocks JMP (@Start,D4.W*2) ;blast them out @DoSixteen EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ EOR.L D6,(a2)+ @Start EOR.L D6,(a2)+ DBRA D3,@DoSixteen BRA.S @inst rMASK10 EQU @runs ;------------------------------------------------------- ; ; MODE 11 OR 15: PATTERN BIC DST --> DST ; rMASK11 move.l bColor(a6),fColor(a6) ;set up mask color for BIC mode lea rMask9,a2 ;point to pattern OR loop move.l a2,modeCase(a6) ;go there from now on jmp (a2) ;------------------------------------------------------- ; ; MODE 8 OR 12: Big PATTERN --> DST (FILLING AREAS, DRAWING LINES) ; ;------------------------------------------------------- ; a0 = tmpsrc d0 = vert ; a1 = tmpmask d1 = scanCount ; a2 = tmpdst d2 = dstRow ; a3 = srcPtr/patPtr d3 = run cnt/hBump/scratch ; a4 = runPtr d4 = fColor/scratch ; a5 = dstPtr d5 = bColor/scratch ; a6 = locals d6 = pattern/pat index/shift cnt ; a7 = d7 = pat select/invert ;------------------------------------------------------- ; <10> Start of alpha changes block from QDciPatchROM.a stb rXMASK8 LEA rXMASK8G,A2 ;get address of normal loop TST.B alphaMode(A6) ;drawing in alpha mode? BEQ.S @1 ;no, use normal loop LEA rXMASK8A,A2 ;get address of alpha loop @1: MOVE.L A2,modeCase(A6) ;save proc address JMP (A2) ;go there now ALIGN Alignment @nxtScan MOVE PATHPOS(A6),D6 ;GET HORIZONTAL POSITION SWAP D6 ;GET VERT POSITION IN PATTERN ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ;LEAVE PATVPOS IN D6 add.l d2,a5 ;BUMP DST TO NEXT ROW MOVE vert(A6),D0 ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask MOVE D0,vert(A6) @runs move.l a5,a2 ;set up destAddr move.l a3,a0 ;set up srcAddr MOVEQ #0,D4 ;clear out high word MOVE D6,D4 ;get vert pattern offset ADD.L D4,A0 ;BUMP TO PROPER ROW SWAP D6 ;AND GET PATHPOS move.l a4,A1 ;point to run encoded mask buffer MOVE.L alphaMask(A6),D5 @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan add.w d3,a2 ;bump destptr by skip amount ADD.W D3,D6 ;BUMP PATTERN POS AND D7,D6 ;WRAP WHEN PATTERN REPEATS swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag BEQ.S @blit @mask MOVE.L 0(A0,D6),D0 ;GET PATTERN DATA ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS MOVE.L (A2),D4 ;GET DST EOR.L D4,D0 ;COMBINE DST AND PATTERN AND.L (A1)+,D0 ;APPLY REGION MASK AND.L D5,D0 ;APPLY ALPHA MASK EOR.L D4,D0 ;REAPPLY DST TO PATTERN MOVE.L D0,(A2)+ ;PUT RESULT TO DST DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit MOVE.L 0(A0,D6),D0 ;GET PATTERN DATA ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS MOVE.L (A2),D4 ;GET DST EOR.L D4,D0 ;COMBINE DST AND PATTERN AND.L D5,D0 ;APPLY ALPHA MASK EOR.L D4,D0 ;REAPPLY DST TO PATTERN MOVE.L D0,(A2)+ ;PUT RESULT TO DST DBRA D3,@blit ;LOOP ALL LONGS THIS ROW BRA.S @inst ;LOOP BACK FOR MORE RUNS rXMASK8A equ @runs ; <10> End of alpha changes block ALIGN Alignment ;------------------------------------------------------- ; ; MODE 8 OR 12: Big PATTERN --> DST (FILLING AREAS, DRAWING LINES) ; ;------------------------------------------------------- ; a0 = tmpsrc d0 = vert ; a1 = tmpmask d1 = scanCount ; a2 = tmpdst d2 = dstRow ; a3 = srcPtr/patPtr d3 = run cnt/hBump/scratch ; a4 = runPtr d4 = fColor/scratch ; a5 = dstPtr d5 = bColor/scratch ; a6 = locals d6 = pattern/pat index/shift cnt ; a7 = d7 = pat select/invert ;------------------------------------------------------- @nxtScan MOVE PATHPOS(A6),D6 ;GET HORIZONTAL POSITION SWAP D6 ;GET VERT POSITION IN PATTERN ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ;LEAVE PATVPOS IN D6 add.l d2,a5 ;BUMP DST TO NEXT ROW ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask ;rXMASK8 @runs move.l a5,a2 ;set up destAddr move.l a3,a0 ;set up srcAddr MOVEQ #0,D5 ;clear out high word MOVE D6,D5 ;get vert pattern offset ADD.L D5,A0 ;BUMP TO PROPER ROW SWAP D6 ;AND GET PATHPOS move.l a4,A1 ;point to run encoded mask buffer @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d3,a2 ;bump destptr by skip amount ADD.W D3,D6 ;BUMP PATTERN POS AND D7,D6 ;WRAP WHEN PATTERN REPEATS swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask MOVE.L 0(A0,D6),D5 ;GET PATTERN DATA ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS MOVE.L (A1)+,D4 ;GET MASK AND.L D4,D5 ;MASK PATTERN DATA NOT.L D4 ;MAKE NOTMASK AND.L (A2),D4 ;GET DST DATA OR.L D4,D5 ;MERGE WITH PAT DATA MOVE.L D5,(A2)+ ;PUT RESULT TO DST DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit MOVE.L 0(A0,D6),(A2)+ ;write pattern to dest ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS DBRA D3,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rXMASK8G EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 9 OR 13: Big PATTERN OR DST --> DST ; @nxtScan MOVE PATHPOS(A6),D6 ;GET HORIZONTAL POSITION SWAP D6 ;GET VERT POSITION IN PATTERN ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ;LEAVE PATVPOS IN D6 add.l DstRow(a6),a5 ;BUMP DST TO NEXT ROW ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask ;rXMASK9 @runs move.l fColor(a6),d2 ;set up color mask (should be loaded externally) move.l a5,a2 ;set up destAddr move.l a3,a0 ;set up srcAddr ADD D6,A0 ;BUMP TO PROPER ROW SWAP D6 ;AND GET PATHPOS move.l a4,A1 ;point to run encoded mask buffer @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan add.w d3,a2 ;bump destptr by skip amount ADD.W D3,D6 ;BUMP PATTERN POS AND D7,D6 ;WRAP WHEN PATTERN REPEATS swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask MOVE.L 0(A0,D6),D5 ;GET PATTERN DATA ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS and.l (A1)+,D5 ;MASK PATTERN DATA move.l D5,D4 ;make a copy NOT.L D4 ;MAKE NOTMASK AND.L (A2),D4 ;punch hole in DST DATA and.l d2,d5 ;apply color to masked pattern OR.L D4,D5 ;MERGE WITH PAT DATA MOVE.L D5,(A2)+ ;PUT RESULT TO DST DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit MOVE.L 0(A0,D6),D5 ;GET PATTERN DATA move.l d5,d4 ;make a copy not.l d4 ;make into mask and.l d2,d5 ;apply color to pattern and.l (a2),d4 ;punch hole in dest ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS or.l d4,d5 ;merge src with dst MOVE.L d5,(a2)+ ;write pattern to dest DBRA D3,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rXMASK9 EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 10 OR 14: Big PATTERN XOR DST --> DST (INVERTING AREAS, XOR LINES) ; @nxtScan MOVE PATHPOS(A6),D6 ;GET HORIZONTAL POSITION SWAP D6 ;GET VERT POSITION IN PATTERN ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ;LEAVE PATVPOS IN D6 add.l d2,a5 ;BUMP DST TO NEXT ROW ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ble.s nextMask ;rXMASK10 @runs move.l a5,a2 ;set up destAddr move.l a3,a0 ;set up srcAddr ADD D6,A0 ;BUMP TO PROPER ROW SWAP D6 ;AND GET PATHPOS move.l a4,A1 ;point to run encoded mask buffer @inst move.l (a1)+,d3 ;pick up next instruction long bmi.s @nxtScan add.w d3,a2 ;bump destptr by skip amount ADD.W D3,D6 ;BUMP PATTERN POS AND D7,D6 ;WRAP WHEN PATTERN REPEATS swap d3 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d3 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask MOVE.L 0(A0,D6),D5 ;GET PATTERN DATA AND.L (A1)+,D5 ;MASK PATTERN DATA ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS EOR.L D5,(A2)+ ;XOR RESULT TO DST DBRA D3,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit MOVE.L 0(A0,D6),D5 ;GET PATTERN DATA ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS EOR.L d5,(a2)+ ;xor pattern to dest DBRA D3,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs rXMASK10 EQU @runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 11 OR 15: Big PATTERN BIC DST --> DST ; rXMASK11 move.l bColor(a6),fColor(a6) ;set up mask color for BIC mode lea rxMask9,a2 ;point to Big pattern OR loop move.l a2,modeCase(a6) ;go there from now on jmp (a2) ALIGN Alignment ;------------------------------------------------------- ; a0 = scratch/cTabPtr d0 = scratch/result ; a1 = scratch/dest RGB d1 = scratch/patHMask ; a2 = scratch/src RGB d2 = pixel cnt ; a3 = srcPtr d3 = hbump ; a4 = RGNBUFFER d4 = offset into destination ; a5 = dstPtr d5 = iTabRes ; a6 = locals d6 = offset into src/pattern ; a7 = d7 = dst pixel size ;------------------------------------------------------- ; ; MODE 34, 42, 58: SRC + DST --> DST (no pin) rAddOver rAddOverIndexed MOVE.L colorTable(A6),A0 ;set up color table MOVE patHMask(A6),D1 ;set up source constriction @loopTop AND D1,D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask region BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source LEA red(A0,D0*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D4:D7},D0 ;a pixel of the destination LEA red(A0,D0*8),A1 ;figure out where destination lives MOVE (A2)+,D0 ;red get source color value ADD (A1)+,D0 ; combine source and destination ASL.L D5,D0 ; save the top bits in the top word MOVE (A2)+,D0 ;green get source color value ADD (A1)+,D0 ; combine source and destination ASL.L D5,D0 ; save the top bits in the top word MOVE (A2)+,D0 ;blue get source color value ADD (A1)+,D0 ; combine source and destination ASL.L D5,D0 ; save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = hi bit clring mask ; a1 = maskPtr d1 = scanCount ; a2 = hi bit mask d2 = run cnt ; a3 = srcPtr/patPtr d3 = dst msb's ; a4 = hBump d4 = src msb's ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rAddOver32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.l #~$ff808080,d0 ;get high bit clearing mask move.l #$00808080,a2 ;get high bit mask swap d1 ;move line count to high word move.w patHMask(a6),d1 ;put pattern hmask in low word @inst swap d1 ;swap line count into low word move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 swap d1 ;swap pattern hmask into low word add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d1,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel move.l a2,d4 ;copy high bit mask and.l d7,d4 ;remember src msb's and.l d0,d7 ;mask out stragglers move.l (a5),d5 ;get dest pixel move.l a2,d3 ;copy high bit mask and.l d5,d3 ;remember dst msb's and.l d0,d5 ;mask out stragglers add.l d7,d5 ;merge src with dst eor.l d4,d3 ;compute partial sum of msb's eor.l d3,d5 ;compute partial sum of msb's MOVE.L d5,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr add a4,d6 ;bump src index and.w d1,d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = hi bit clring mask ; a1 = maskPtr d1 = scanCount ; a2 = hi bit mask d2 = run cnt ; a3 = srcPtr/patPtr d3 = dst msb's ; a4 = hBump d4 = src msb's ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rAddOver16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.w #$3def,d0 ;get high bit clearing mask move.w #$4210,a2 ;get high bit mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne move.w 0(a0,d6.w),d7 ;get src pixel move.w a2,d4 ;copy high bit mask and.w d7,d4 ;remember src msb's and.w d0,d7 ;mask out stragglers move.w (a5),d5 ;get dest pixel move.w a2,d3 ;copy high bit mask and.w d5,d3 ;remember dst msb's and.w d0,d5 ;mask out stragglers add.w d7,d5 ;merge src with dst eor.w d4,d3 ;compute partial sum of msb's eor.w d3,d5 ;compute partial sum of msb's move.w d5,(a5) ;write pattern to dest rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 33, 41, 57: SRC + DST --> DST (pin to max) ; in addition to the registers set up for AddOver, this needs ; the 3 element word array pin(A6) to be set to the maximum g, b, r values (in that order) ; for comparison and pinning ; Note that AddPin is not unwound while AddOver is; unwinding AddPin would gain less than ; 10%; is it worth it? (Would it make any difference to the cache?) ; Would anyone care? Andy?? rAddPin rAddPinIndexed MOVE.L colorTable(A6),A0 ;set up color table @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask region BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source LEA red(A0,D0*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D4:D7},D0 ;a pixel of the destination LEA red(A0,D0*8),A1 ;figure out where destination lives MOVEQ #2,D1 ;repeat for r, g, & b @nextColor MOVE (A2)+,D0 ;get source color value ADD (A1)+,D0 ;combine source and destination BCS.S @tooBig CMP (pin,A6,D1*2),D0 ;bigger than pin value? BLS.S @notTooBig ;no, no problem @tooBig MOVE (pin,A6,D1*2),D0 @notTooBig ASL.L D5,D0 ;save the top bits in the top word DBRA D1,@nextColor SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = lo3Bytes mask(scanCount) ; a2 = scanCount d2 = run cnt ; a3 = srcPtr/patPtr d3 = pin pixel 0rgb ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rAddPin32 lea AddPin32,a0 ;point to main loop move.l a0,modeCase(a6) ;go there from now on ;set up 8-8-8 pin pixel as 0rgb in D3 moveq #0,d3 ;start fresh, waste iTabRes move.b pin+4(a6),d3 ;pick up red swap d3 ;put in byte 3 move.w pin+2(a6),d3 ;get green in byte 2 move.b pin(a6),d3 ;put blue in lo byte AddPin32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.l d1,a2 ;save scanCount in a2 move.l Lo3Bytes,d1 ;pick up mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi NxtNewSrc32b ;restore scanCount and bump to next scan add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode and.l d1,d7 ;waste high byte move.l d7,d0 ;make a copy of the src xrgb move.l (a5),d5 ;get dest pixel and.l d1,d5 ;waste high byte clr.b d0 ;prevent carries from below add.w d5,d0 ;add green components BCS.S @PinGreen cmp.w d3,d0 ;do we need to pin result? bls.s @GreenOK @PinGreen move.w d3,d0 ;use pin value instead @GreenOK move.b d7,d0 ;get src blue add.b d5,d0 ;add dest blue BCS.S @PinBlue cmp.b d3,d0 ;do we need to pin result? bls.s @BlueOK @PinBlue move.b d3,d0 ;use pin value instead @BlueOK clr.w d5 ;now d5 has only red in byte 3 add.l d5,d0 ;add red components cmp.l d3,d0 ;compare red components bls.s @RedOK @PinRed swap d3 ;get max red in lo word swap d0 ;get too big red in lo word move.w d3,d0 ;pin to max red swap d0 ;get back 0rgb swap d3 ;restore pin pixel @RedOK MOVE.L d0,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = lo3Bytes mask(scanCount) ; a2 = scanCount d2 = run cnt ; a3 = srcPtr/patPtr d3 = pin pixel 0rgb ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rAddPin16 lea AddPin16,a0 ;point to main loop move.l a0,modeCase(a6) ;go there from now on ;set up 5-5-5 pin pixel as 0rgb in D3 moveq #0,d3 ;start fresh, waste iTabRes move.b pin+4(a6),d3 ;pick up red lsr.b #3,d3 ;get right aligned 5 bits swap d3 ;put in byte 3 move.w pin+2(a6),d3 ;get green in byte 2 lsr.w #3,d3 ;get right aligned 5 bits move.b pin(a6),d3 ;put blue in lo byte lsr.b #3,d3 ;right flush blue AddPin16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.w #$3def,d0 ;get high bit clearing mask move.w #$4210,a2 ;get high bit mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne moveq #0,d7 move.w 0(a0,d6.w),d7 ;get src pixel add.w d7,d7 ;waste high bit lsl.l #5,d7 ;but red in byte 3 lsr.w #3,d7 ;but green in byte 2, blue in lo byte lsr.b #3,d7 ;right flush blue moveq #0,d5 move.w (a5),d5 ;get a pixel of the dest xrgb add.w d5,d5 ;waste high bit lsl.l #5,d5 ;but red in byte 3 lsr.w #3,d5 ;but green in byte 2, blue in lo byte lsr.b #3,d5 ;right flush blue add.l d5,d7 ;add all components at once move.l d7,d0 ;prime result with red cmp.l d3,d0 ;do we need to pin result? bls.s @redOK ;no, don't pin move.l d3,d0 ;use pin value instead @redOK move.w d7,d0 ;prime result with green cmp.w d3,d0 ;do we need to pin result? bls.s @greenOK ;no, don't pin move.w d3,d0 ;use pin value instead @greenOK move.b d7,d0 ;prime result with blue cmp.b d3,d0 ;do we need to pin result? bls.s @blueOK ;no, don't pin move.b d3,d0 ;use pin value instead @blueOK lsl.b #3,d0 ;rejoin green/blue lsl.w #3,d0 ;rejoin red/green/blue lsr.l #6,d0 ;right flush red/green/blue move.w d0,(a5) ;move to the destination rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 38, 46, 62: DST - SRC --> DST (no pin) ; ; rSubOver rSubOverIndexed MOVE.L colorTable(A6),A0 ;set up color table MOVE patHMask(A6),D1 ;set up source constriction @loopTop AND D1,D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask region BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source LEA red(A0,D0*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D4:D7},D0 ;a pixel of the destination LEA red(A0,D0*8),A1 ;figure out where destination lives MOVE (A1)+,D0 ;red get destination color value SUB (A2)+,D0 ; less source color value ASL.L D5,D0 ; save the top bits in the top word MOVE (A1)+,D0 ;green get destination color value SUB (A2)+,D0 ; less source color value ASL.L D5,D0 ; save the top bits in the top word MOVE (A1)+,D0 ;blue get destination color value SUB (A2)+,D0 ; less source color value ASL.L D5,D0 ; save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = hi bit clring mask ; a1 = maskPtr d1 = high bit mask (scanCount) ; a2 = scanCount d2 = run cnt ; a3 = srcPtr/patPtr d3 = src msb's ; a4 = hBump d4 = dst msb's ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rSubOver32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.l d1,a2 ;save scanCount in a2 move.l #~$ff808080,d0 ;get high bit clearing mask move.l #$00808080,d1 ;get high bit mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi NxtNewSrc32b ;restore scanCount and bump to next scan add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel move.l d1,d3 ;copy high bit mask and.l d7,d3 ;remember src msb's eor.l d1,d3 ;invert src msb's and.l d0,d7 ;mask out stragglers move.l (a5),d5 ;get a pixel of the dest xrgb move.l d1,d4 ;copy high bit mask and.l d5,d4 ;remember dst msb's and.l d0,d5 ;mask out high byte or.l d1,d5 ;force high bits on sub.l d7,d5 ;compute dst - src eor.l d3,d4 ;compute partial sum of msb's eor.l d4,d5 ;compute partial sum of msb's MOVE.L d5,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr add a4,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = hi bit clring mask ; a1 = maskPtr d1 = high bit mask ; a2 = scancount d2 = run cnt ; a3 = srcPtr/patPtr d3 = dst msb's ; a4 = hBump d4 = src msb's ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rSubOver16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.l d1,a2 ;save scancount move.w #$3def,d0 ;get high bit clearing mask move.w #$4210,d1 ;get high bit mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32b add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne move.w d1,d3 ;copy high bit mask move.w 0(a0,d6.w),d7 ;get src pixel and.w d7,d3 ;remember src msb's eor.w d1,d3 ;invert src msb's and.w d0,d7 ;mask out stragglers move.w (a5),d5 ;get dest pixel move.w d1,d4 ;copy high bit mask and.w d5,d4 ;remember dst msb's and.w d0,d5 ;mask out high byte or.w d1,d5 ;force high bits on sub.w d7,d5 ;compute dst - src eor.w d3,d4 ;compute partial sum of msb's eor.w d4,d5 ;compute partial sum of msb's move.w d5,(a5) ;write pattern to dest rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 35, 43, 59: DST - SRC --> DST (pin to min) rSubPin rSubPinIndexed MOVE.L colorTable(A6),A0 ;set up color table @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask region BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source LEA red(A0,D0*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D4:D7},D0 ;a pixel of the destination LEA red(A0,D0*8),A1 ;figure out where destination lives MOVEQ #2,D1 ;repeat for r, g, & b @nextColor MOVE (A1)+,D0 ;get destination color value SUB (A2)+,D0 ;less source color value BCS.S @tooBig CMP (pin,A6,D1*2),D0 ;bigger than pin value? BHS.S @notTooBig ;no, no problem @tooBig MOVE (pin,A6,D1*2),D0 @notTooBig ASL.L D5,D0 ;save the top bits in the top word DBRA D1,@nextColor SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = lo3Bytes mask(scanCount) ; a2 = scanCount d2 = run cnt ; a3 = srcPtr/patPtr d3 = pin pixel 0rgb ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = src pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = dst pixel ;------------------------------------------------------- rSubPin32 lea SubPin32,a0 ;point to main loop move.l a0,modeCase(a6) ;go there from now on ;set up 8-8-8 pin pixel as 0rgb in D3 moveq #0,d3 ;start fresh, waste iTabRes move.b pin+4(a6),d3 ;pick up red swap d3 ;put in byte 3 move.w pin+2(a6),d3 ;get green in byte 2 move.b pin(a6),d3 ;put blue in lo byte SubPin32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.l d1,a2 ;save scanCount in a2 move.l Lo3Bytes,d1 ;pick up mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi NxtNewSrc32b ;restore scanCount and bump to next scan add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d5 ;get src pixel add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode and.l d1,d5 ;waste high byte move.l (a5),d7 ;get dest pixel and.l d1,d7 ;waste high byte move.l d7,d0 ;make a copy of the dst xrgb st d0 ;prevent borrows from below sub.w d5,d0 ;sub green components BCS.S @PinGreen cmp.w d3,d0 ;do we need to pin result? bhs.s @GreenOK @PinGreen move.w d3,d0 ;use pin value instead @GreenOK move.b d7,d0 ;get dest blue sub.b d5,d0 ;sub src blue BCS.S @PinBlue cmp.b d3,d0 ;do we need to pin result? bhs.s @BlueOK @PinBlue move.b d3,d0 ;use pin value instead @BlueOK clr.w d5 ;now d5 has only red in byte 3 sub.l d5,d0 ;sub red components cmp.l d3,d0 ;compare red components bge.s @RedOK @PinRed swap d3 ;get max red in lo word swap d0 ;get too big red in lo word move.w d3,d0 ;pin to max red swap d0 ;get back 0rgb swap d3 ;restore pin pixel @RedOK MOVE.L d0,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = lo3Bytes mask(scanCount) ; a2 = scanCount d2 = run cnt ; a3 = srcPtr/patPtr d3 = pin pixel 0rgb ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rSubPin16 lea SubPin16,a0 ;point to main loop move.l a0,modeCase(a6) ;go there from now on ;set up 5-5-5 pin pixel as 0rgb in D3 moveq #0,d3 ;start fresh, waste iTabRes move.b pin+4(a6),d3 ;pick up red lsr.b #3,d3 ;get right aligned 5 bits swap d3 ;put in byte 3 move.w pin+2(a6),d3 ;get green in byte 2 lsr.w #3,d3 ;get right aligned 5 bits move.b pin(a6),d3 ;put blue in lo byte lsr.b #3,d3 ;right flush blue add.l #$808080,d3 ;prevent borrows from crossing byte boundaries SubPin16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.l d1,a2 ;save scancount move.l #$808080,d1 ;borrow stopper @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32b add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne moveq #0,d5 move.w 0(a0,d6.w),d5 ;get src pixel add.w d5,d5 ;waste high bit lsl.l #5,d5 ;but red in byte 3 lsr.w #3,d5 ;but green in byte 2, blue in lo byte lsr.b #3,d5 ;right flush blue moveq #0,d7 move.w (a5),d7 ;get a pixel of the dest xrgb add.w d7,d7 ;waste high bit lsl.l #5,d7 ;but red in byte 3 lsr.w #3,d7 ;but green in byte 2, blue in lo byte lsr.b #3,d7 ;right flush blue add.l d1,d7 ;prevent borrows from crossing byte boundaries sub.l d5,d7 ;sub all components at once move.l d7,d0 ;prime result with red cmp.l d3,d0 ;do we need to pin result? bhs.s @redOK ;no, don't pin move.l d3,d0 ;use pin value instead @redOK move.w d7,d0 ;prime result with green cmp.w d3,d0 ;do we need to pin result? bhs.s @greenOK ;no, don't pin move.w d3,d0 ;use pin value instead @greenOK move.b d7,d0 ;prime result with blue cmp.b d3,d0 ;do we need to pin result? bhs.s @blueOK ;no, don't pin move.b d3,d0 ;use pin value instead @blueOK lsl.b #3,d0 ;rejoin green/blue lsl.w #3,d0 ;rejoin red/green/blue lsr.l #6,d0 ;right flush red/green/blue move.w d0,(a5) ;move to the destination rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 37, 45, 61: MAX(SRC, DST) --> DST ; ; rMax rMaxIndexed MOVE.L colorTable(A6),A0 ;set up color table MOVE patHMask(A6),D1 ;set up source constriction @loopTop AND D1,D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask region BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source LEA red(A0,D0*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D4:D7},D0 ;a pixel of the destination LEA red(A0,D0*8),A1 ;figure out where destination lives MOVE (A2)+,D0 ;red get source color value CMP (A1),D0 ; compare source and destination BHS.S @gotTheMaxRed MOVE (A1),D0 @gotTheMaxRed ADDQ #2,A1 ;advance to next color ASL.L D5,D0 ; save the top bits in the top word MOVE (A2)+,D0 ;green get source color value CMP (A1),D0 ; compare source and destination BHS.S @gotTheMaxGreen MOVE (A1),D0 @gotTheMaxGreen ADDQ #2,A1 ;advance to next color ASL.L D5,D0 ; save the top bits in the top word MOVE (A2)+,D0 ;blue get source color value CMP (A1),D0 ; compare source and destination BHS.S @gotTheMaxBlue MOVE (A1),D0 @gotTheMaxBlue ASL.L D5,D0 ;save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = scanCount ; a2 = d2 = run cnt ; a3 = srcPtr/patPtr d3 = ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rMax32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode move.l (a5),d5 ;get dest pixel move.l d5,d0 ;make a copy of the dest xrgb cmp.w d7,d0 ;compare g,b components BHI.S @gotMaxGreen move.w d7,d0 ;keep the bigger of the two move.b d5,d0 ;prime for blue @gotMaxGreen cmp.b d7,d5 ;compare blue components BHI.S @gotMaxBlue move.b d7,d0 ;keep the bigger of the two @gotMaxBlue swap d7 swap d0 cmp.b d7,d0 ;compare red components BHI.S @gotMaxRed move.b d7,d0 ;keep the bigger of the two @gotMaxRed swap d0 ;get new xrgb MOVE.L d0,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = ; a2 = scanCount d2 = run cnt ; a3 = srcPtr/patPtr d3 = ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rMax16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne moveq #0,d7 move.w 0(a0,d6.w),d7 ;get src pixel add.w d7,d7 ;waste high bit lsl.l #5,d7 ;but red in byte 3 lsr.w #3,d7 ;but green in byte 2, blue in lo byte lsr.b #3,d7 ;right flush blue moveq #0,d5 move.w (a5),d5 ;get a pixel of the dest xrgb add.w d5,d5 ;waste high bit lsl.l #5,d5 ;but red in byte 3 lsr.w #3,d5 ;but green in byte 2, blue in lo byte lsr.b #3,d5 ;right flush blue move.l d7,d0 ;prime result with src cmp.l d5,d0 ;is dst greater? bhs.s @gotRed ;no, use src move.l d5,d0 ;use dst value instead @gotRed move.w d7,d0 ;prime result with src cmp.w d5,d0 ;is dst greater? bhs.s @gotGreen ;no, use src move.w d5,d0 ;use dst value instead @gotGreen move.b d7,d0 ;prime result with src cmp.b d5,d0 ;is dst greater? bhs.s @gotBlue ;no, use src move.b d5,d0 ;use dst value instead @gotBlue lsl.b #3,d0 ;rejoin green/blue lsl.w #3,d0 ;rejoin red/green/blue lsr.l #6,d0 ;right flush red/green/blue move.w d0,(a5) ;move to the destination rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 39, 47, 63: MIN(SRC, DST) --> DST ; ; Note: D4 is unused rMin rMinIndexed MOVE.L colorTable(A6),A0 ;set up color table MOVE patHMask(A6),D1 ;set up source constriction @loopTop AND D1,D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask region BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source LEA red(A0,D0*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D4:D7},D0 ;a pixel of the destination LEA red(A0,D0*8),A1 ;figure out where destination lives MOVE (A2)+,D0 ;red get source color value CMP (A1),D0 ; compare source and destination BLS.S @gotTheMinRed MOVE (A1),D0 @gotTheMinRed ADDQ #2,A1 ;advance to next color ASL.L D5,D0 ; save the top bits in the top word MOVE (A2)+,D0 ;green get source color value CMP (A1),D0 ; compare source and destination BLS.S @gotTheMinGreen MOVE (A1),D0 @gotTheMinGreen ADDQ #2,A1 ;advance to next color ASL.L D5,D0 ; save the top bits in the top word MOVE (A2)+,D0 ;blue get source color value CMP (A1),D0 ; compare source and destination BLS.S @gotTheMinBlue MOVE (A1),D0 @gotTheMinBlue ASL.L D5,D0 ;save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = scanCount ; a2 = d2 = run cnt ; a3 = srcPtr/patPtr d3 = ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rMin32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode move.l (a5),d5 ;get dest pixel move.l d5,d0 ;make a copy of the dest xrgb cmp.w d7,d0 ;compare g,b components BLS.S @gotMinGreen move.w d7,d0 ;keep the smaller of the two move.b d5,d0 ;prime for blue @gotMinGreen cmp.b d7,d5 ;compare blue components BLS.S @gotMinBlue move.b d7,d0 ;keep the smaller of the two @gotMinBlue swap d7 swap d0 cmp.b d7,d0 ;compare red components BLS.S @gotMinRed move.b d7,d0 ;keep the smaller of the two @gotMinRed swap d0 ;get new xrgb MOVE.L d0,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = ; a2 = scanCount d2 = run cnt ; a3 = srcPtr/patPtr d3 = ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rMin16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne moveq #0,d7 move.w 0(a0,d6.w),d7 ;get src pixel add.w d7,d7 ;waste high bit lsl.l #5,d7 ;but red in byte 3 lsr.w #3,d7 ;but green in byte 2, blue in lo byte lsr.b #3,d7 ;right flush blue moveq #0,d5 move.w (a5),d5 ;get a pixel of the dest xrgb add.w d5,d5 ;waste high bit lsl.l #5,d5 ;but red in byte 3 lsr.w #3,d5 ;but green in byte 2, blue in lo byte lsr.b #3,d5 ;right flush blue move.l d7,d0 ;prime result with src cmp.l d5,d0 ;is dst greater? bls.s @gotRed ;no, use src move.l d5,d0 ;use dst value instead @gotRed move.w d7,d0 ;prime result with src cmp.w d5,d0 ;is dst greater? bls.s @gotGreen ;no, use src move.w d5,d0 ;use dst value instead @gotGreen move.b d7,d0 ;prime result with src cmp.b d5,d0 ;is dst greater? bls.s @gotBlue ;no, use src move.b d5,d0 ;use dst value instead @gotBlue lsl.b #3,d0 ;rejoin green/blue lsl.w #3,d0 ;rejoin red/green/blue lsr.l #6,d0 ;right flush red/green/blue move.w d0,(a5) ;move to the destination rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 32, 40, 56: AVG(SRC, DST, WEIGHT) --> DST rAvg rAvgIndexed MOVE.L D3,A0 ;free up data register, get pixel bump @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask region BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source (zeros top word) LEA ([colorTable,A6],D0*8,red),A2 ;figure out where it lives in the color table BFEXTU (A5){D4:D7},D0 ;a pixel of the destination LEA ([colorTable,A6],D0*8,red),A1 ;figure out where destination lives MOVEQ #2,D0 ;once for each color MOVE invSize(A6),D3 ;do once for r, b and g ADD D3,D3 ;initialize at 2x for shift count CLR -(SP) ;make space & initialize average r, b, g @nextColor MOVE (A2)+,D1 ;get source color value MULU (weight,A6,D0*2),D1 ;weight varies from 0 to 1 MOVE (A1)+,D5 ;get destination color value MULU (notWeight,A6,D0*2),D5 ;weight varies from 1 to 0 ADD.L D5,D1 ;add source + dest SWAP D1 ;high word is interesting part MOVE rtShift(A6),D5 ;amount to shift right LSR D5,D1 ;get top bits only LSL D3,D1 ;shift by 2x, 1x, or 0 (for r, g, & b) OR D1,(SP) ;combine r, g, b SUB invSize(A6),D3 ;decrement shift, weight index DBRA D0,@nextColor ;do for b & g as well MOVE (SP)+,D0 ;r, g, b MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L A0,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L A0,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVE.L A0,D3 ;restore bump for next time through BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit mask ; a1 = maskPtr d1 = (scanCount) ; a2 = low bit mask d2 = run cnt ; a3 = srcPtr/patPtr d3 = lsb's of result ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rAvg32Half move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.l #~$ff808080,d0 ;get high bit mask move.l #$10101,a2 ;get low bit mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi NxtNewSrc32 ;bump to next scanline add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode move.l a2,d3 ;copy low bit mask and.l d7,d3 ;remember src lsb's lsr.l #1,d7 ;get almost 1/2 of it and.l d0,d7 ;mask out stragglers move.l (a5),d5 ;get dest pixel and.l d5,d3 ;compute carry out of lsb lsr.l #1,d5 ;get almost 1/2 of it and.l d0,d5 ;mask out stragglers add.l d5,d7 ;merge src with dst add.l d3,d7 ;propagate carrys MOVE.L d7,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit mask ; a1 = maskPtr d1 = (scanCount) ; a2 = low bit mask d2 = run cnt ; a3 = srcPtr/patPtr d3 = lsb's of result ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rAvg16Half move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.w #$3def,d0 ;get high bit clearing mask move.w #$0421,a2 ;get high bit mask @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne move.l a2,d3 ;copy low bit mask move.w 0(a0,d6.w),d7 ;get src pixel and.w d7,d3 ;remember src lsb's lsr.w #1,d7 ;get almost 1/2 of it and.w d0,d7 ;mask out stragglers move.w (a5),d5 ;get dest pixel and.w d5,d3 ;compute carry out of lsb lsr.w #1,d5 ;get almost 1/2 of it and.w d0,d5 ;mask out stragglers add.w d5,d7 ;merge src with dst add.w d3,d7 ;propagate carrys move.w d7,(a5) ;write pattern to dest rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = red weight ; a1 = maskPtr d1 = blue/grn weight (scanCount) ; a2 = scratch d2 = run cnt ; a3 = srcPtr/patPtr d3 = scratch ; a4 = hBump d4 = scratch ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- nxtScanRAvg32 move.w (sp)+,d1 ;reload scanCount bra NxtNewSrc32 ;bump to next scanline rAvg32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.w d1,-(sp) ;save scanCount lea weight(a6),a2 ;point at blue weight move.l (a2)+,d1 ;get blue/green weight move.w (a2),d0 ;get red weight @short0 moveq #0,d4 ;init last result move.l d4,d3 ;init last src move.l d4,a2 ;init last dst @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s nxtScanRAvg32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel add a4,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode move.l (a5),d5 ;get dest pixel @short1 cmp.l d3,d7 ;same as last time? bne.s @blue ;no, go do it cmp.l a2,d5 ;same as last time? beq.s @again ;yes, go fast @blue moveq #0,d3 ;clr out high end move.b d7,d3 ;get src blue swap d1 ;get blue weight mulu.w d1,d3 ;% blue moveq #0,d4 ;clr out high end move.b d5,d4 ;get dst blue neg.w d1 mulu.w d1,d4 ;% blue neg.w d1 add.l d3,d4 ;get 24 bits of dst blue swap d4 ;dst blue move.w d4,a2 ;a2 has 000B @grn move.w d7,d3 ;get src grn lsr.w #8,d3 swap d1 ;get grn weight mulu.w d1,d3 ;% grn move.w d5,d4 ;get dst grn lsr.w #8,d4 neg.w d1 mulu.w d1,d4 ;% grn neg.w d1 add.l d3,d4 ;get 24 bits of dst grn swap d4 ;dst grn lsl.w #8,d4 add.w d4,a2 ;a2 has 00GB @red moveq #0,d3 ;clr out high end swap d7 move.b d7,d3 ;get src red mulu.w d0,d3 ;% red moveq #0,d4 ;clr out high end swap d5 move.b d5,d4 ;get dst red neg.w d0 mulu.w d0,d4 ;% red neg.w d0 add.l d3,d4 ;get 24 bits of dst red move.w a2,d4 ;d4 has 0RGB @short2 swap d5 ;get back dst move.l d5,a2 ;save for short circuit swap d7 ;get back src move.l d7,d3 ;save for short circuit @again MOVE.L d4,(a5) ;write pattern to dest add a4,a5 ;bump dst ptr DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = red weight ; a1 = maskPtr d1 = blue/grn weight (scanCount) ; a2 = scratch d2 = run cnt ; a3 = srcPtr/patPtr d3 = scratch ; a4 = hBump d4 = scratch ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rAvg16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer move.w d1,-(sp) ;save scanCount lea weight(a6),a2 ;point at blue weight move.l (a2)+,d1 ;get blue/green weight move.w (a2),d0 ;get red weight @short0 moveq #0,d4 ;init last result move.l d4,d3 ;init last src move.l d4,a2 ;init last dst @inst move.l (a1)+,d2 ;pick up next instruction long bmi nxtScanRAvg32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;dump out second pixel addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first bsr.s @doOne ;dump out first pixel addq #4,a5 ;bump dst ptr addq #4,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @doOne moveq #0,d7 move.w 0(a0,d6.w),d7 ;get src pixel moveq #0,d5 move.w (a5),d5 ;get dest pixel @short1 cmp.w d3,d7 ;same as last time? bne.s @hardway ;no, go do it cmp.w a2,d5 ;same as last time? beq.s @again ;yes, go fast @hardway add.w d7,d7 ;waste high bit lsl.l #5,d7 ;but red in byte 3 lsr.w #3,d7 ;but green in byte 2, blue in lo byte lsr.b #3,d7 ;right flush blue add.w d5,d5 ;waste high bit lsl.l #5,d5 ;but red in byte 3 lsr.w #3,d5 ;but green in byte 2, blue in lo byte lsr.b #3,d5 ;right flush blue @blue moveq #0,d3 ;clr out high end move.b d7,d3 ;get src blue swap d1 ;get blue weight mulu.w d1,d3 ;% blue moveq #0,d4 ;clr out high end move.b d5,d4 ;get dst blue neg.w d1 mulu.w d1,d4 ;% blue neg.w d1 add.l d3,d4 ;get 21 bits of blue swap d4 ;right align 5 blue bits move.l d4,a2 ;a2 has 000B @grn move.w d7,d3 ;get src grn lsr.w #8,d3 swap d1 ;get grn weight mulu.w d1,d3 ;% grn move.w d5,d4 ;get dst grn lsr.w #8,d4 neg.w d1 mulu.w d1,d4 ;% grn neg.w d1 add.l d3,d4 ;get 21 bits of grn swap d4 ;right align 5 green bits lsl.w #5,d4 ;shift into place add.w d4,a2 ;a2 has 00GB @red moveq #0,d3 ;clr out high end swap d7 move.b d7,d3 ;get src red mulu.w d0,d3 ;% red moveq #0,d4 ;clr out high end swap d5 move.b d5,d4 ;get dst red neg.w d0 mulu.w d0,d4 ;% red neg.w d0 add.l d3,d4 ;get 21 bits of red clr.w d4 ;clear lsb's lsr.l #6,d4 ;shift into place add.w a2,d4 ;d4 has 0RGB @short2 swap d5 ;get back dst lsl.b #3,d5 ;rejoin green/blue lsl.w #3,d5 ;rejoin red/green/blue lsr.l #6,d5 ;right flush red/green/blue move.l d5,a2 ;save for short circuit swap d7 ;get back src lsl.b #3,d7 ;rejoin green/blue lsl.w #3,d7 ;rejoin red/green/blue lsr.l #6,d7 ;right flush red/green/blue move.l d7,d3 ;save for short circuit @again move.w d4,(a5) ;write pattern to dest rts @blit bsr.s @doOne ;do first pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index bsr.s @doOne ;do second pixel in long addq #2,a5 ;bump dst ptr addq #2,d6 ;bump src index and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 58: Hilite DST (similar to invert) ; pattern is black ; do a long at a time when possible ; run masked version ; ;------------------------------------------------------- ; a0 = scanCount d0 = vert/scratch ; a1 = tmpmask d1 = scanCount/scratch ; a2 = tmpdst d2 = dstrow/scratch ; a3 = long of hilite d3 = hilite pixel ; a4 = scratch d4 = scratch ; a5 = dstPtr d5 = long of backcolor ; a6 = locals d6 = background pixel ; a7 = d7 = dst pixel size ;------------------------------------------------------- rHilite runHiliteNot32 lea @rHilit,a0 ;point to main loop move.l a0,modeCase(a6) ;go there from now on move.l hilitColor(A6),a3 ;should be setup only once move.l transColor(A6),d5 ;should be setup only once bra.s @rHilit ;use run mask @nxtScan add.l DstRow(a6),a5 ;BUMP DST TO NEXT ROW move.w vert(a6),d0 ;reload vert ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,a0 ;decrement scanCount move.w a0,d1 ;tst scanCount ble.s nextMask @rHilit move.w d1,a0 ;keep scan count in a0 @runs move.w d0,vert(a6) ;save vert for later move.l a5,a2 ;init tmp dst ptr move.l runBuf(a6),a1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask move.l (a2),d4 ;get dst cmp.l d4,d5 ;is the dst all background? bne.s @mask1AtATime ;handle pixel by pixel @mSwap move.l (a1)+,d0 ;get mask move.l a3,d1 ;get hilite long and.l d0,d1 ;mask hilite long not.l d0 ;make into punch and.l (a2),d0 ;punch hole in dst or.l d0,d1 ;merge src and dst move.l d1,(a2)+ ;put back to dst DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @mask1AtATime cmp.l a3,d4 bne.s @mSlow exg a3,d5 bra.s @mSwap @mSlow MOVEQ #32,D1 ;long position count SUB D7,D1 ;start at last pixel position move.l d5,a4 ;free up a register move.l (a1)+,d5 ;get mask long @mNextPixel BFEXTU d5{D1:D7},D0 ;get a pixel of the mask beq.s @mSkipBlank ;zero so skip this pixel BFEXTU d4{D1:D7},D0 ;get a pixel of the destination CMP.l D6,D0 ;same as the background color? BNE.S @mTryNew BFINS D3,d4{D1:D7} BRA.S @mSkipToNext @mTryNew CMP.l D3,D0 ;same as new color? BNE.S @mSkipToNext BFINS D6,d4{D1:D7} @mSkipToNext @mSkipBlank SUB D7,D1 ;advance to next pixel BPL.S @mNextPixel move.l d4,(a2)+ ;advance the destination move.l a4,d5 ;restore background long DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit move.l (a2),d4 ;get dst cmp.l d4,d5 ;is the dst all background? bne.s @blit1AtATime ;handle pixel by pixel @bSwap move.l a3,(a2)+ ;replace with hilite DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit1AtATime cmp.l a3,d4 bne.s @bSlow exg a3,d5 bra.s @bSwap @bSlow MOVEQ #32,D1 ;long position count SUB D7,D1 ;start at last pixel position @bNextPixel BFEXTU d4{D1:D7},D0 ;get a pixel of the destination CMP.l D6,D0 ;same as the background color? BNE.S @bTryNew BFINS D3,d4{D1:D7} BRA.S @bSkipToNext @bTryNew CMP.l D3,D0 ;same as new color? BNE.S @bSkipToNext BFINS D6,d4{D1:D7} @bSkipToNext SUB D7,D1 ;advance to next pixel BPL.S @bNextPixel move.l d4,(a2)+ ;advance the destination DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; ; MODE 58: Hilite DST (similar to invert) ; Special 32 bit/pixel version of run-masked Hilite ; ;------------------------------------------------------- ; a0 = d0 = vert/scratch ; a1 = tmpmask d1 = scanCount/scratch ; a2 = tmpdst d2 = dstrow/scratch ; a3 = long of hilite d3 = low3bytes ; a4 = scratch d4 = scratch ; a5 = dstPtr d5 = long of backcolor ; a6 = locals d6 = background pixel ; a7 = d7 = dst pixel size ;------------------------------------------------------- rHilite32 lea @Hilite32,a0 ;point to main loop move.l a0,modeCase(a6) ;go there from now on moveq #-1,d3 lsr.l #8,d3 ;get low3byte mask in d0 move.l hilitColor(A6),a3 ;should be setup only once move.l transColor(A6),d5 ;should be setup only once bra.s @Hilite32 ;use run mask @nxtScan add.l DstRow(a6),a5 ;BUMP DST TO NEXT ROW move.w vert(a6),d0 ;reload vert ADDQ #1,D0 ;BUMP DOWN A SCAN LINE CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ? bge DONE ;YES, BAIL subq #1,d1 ;decrement scanCount ble.s nextMask @Hilite32 @runs move.w d0,vert(a6) ;save vert for later move.l a5,a2 ;init tmp dst ptr move.l runBuf(a6),a1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s @nxtScan ;if high bit set then done with scan add.w d2,a2 ;bump destptr by skip amount swap d2 ;get mask/blit cnt and check done flag @blit move.l d3,d4 ;copy mask and.l (a2),d4 ;get dst minus alpha channel cmp.l d4,d5 ;is the dst background? bne.s @chkHilite ;chk for hilite color @bSwap move.l a3,(a2)+ ;replace with hilite DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @chkHilite cmp.l a3,d4 ;is the dst hilite? bne.s @skip ;no, ignore it exg a3,d5 ;yes, exchange back and hilite bra.s @bSwap @skip addq.l #4,a2 ;advance the destination DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ;------------------------------------------------------- ALIGN Alignment ;------------------------------------------------------- ; ; MODES 50 or 58: exchange hilite color with back color (using source, patterns as mask) ; slow hilite does pixel by pixel if not small pattern = black ; ; - This entirely new routine replaces previous "BRA Done" routine. ; this routine comes from QDciPatchROM.a stb ; ;------------------------------------------------------- ; a0 = d0 = scratch ; a1 = bk pixel d1 = patHMask ; a2 = d2 = run cnt ; a3 = srcPtr d3 = bit bump ; a4 = mskPtr d4 = dst offset ; a5 = dstPtr d5 = hilite pixel ; a6 = locals d6 = src offset ; a7 = d7 = dst pixel size ;------------------------------------------------------- rslowHilite CMP #16,D7 ;if 16 or 32 bit/pixel, undo some setup BLT.S @notDirect LSL.L #3,D6 ;turn the patOffset back to pixels from bytes MOVE.L D6,patOffset(A6) MOVE patHMask(A6),D1 ;convert patHMask back into pixels from bytes LSL.W #3,D1 MOVE D1,patHMask(A6) @notDirect LEA @rsHilite,A0 ;get address of real blit loop MOVE.L A0,modeCase(A6) ;go there from now on @rsHilite MOVE patHMask(A6),D1 ;set up source constriction BFEXTU transColor(A6){0:D7},D0 MOVE.L D0,A1 ;set up pixel of background color @loopTop AND D1,D6 ;constrict to the source long if in a pattern mode BFEXTU (A3){D6:D7},D0 ;get pixel of source CMP.L A1,D0 ;is it the same as the background color? BEQ.S @skip ;skip if so BFEXTU (A4){D4:D7},D0 ;get pixel of the mask BEQ.S @skip ;skip if empty BFEXTU (A5){D4:D7},D0 ;get a pixel of the dest (zeros top word) CMP.L A1,D0 ;same as a pixel of the background? BEQ.S @putHilite ;yes, go put hilite there CMP.L D5,D0 ;same as a pixel of the hilite color? BNE.S @skip ;no, skip it MOVE.L A1,D0 BFINS D0,(A5){D4:D7} ;yes, move pixel of back color to dest BRA.S @skip @putHilite BFINS D5,(A5){D4:D7} ;move hilite color to dest @skip ADD.L D3,D6 ;bump srcptr left or right by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;loop back for more ALIGN Alignment ;------------------------------------------------------- ; ; MODES 36, 44, 60: SRC less bg --> DST IMPORT rTransparent8 ;stb This comes from Arith8Blt.a, Andy’s QuickerDraw stuff rTransparent rTransparentIndexed TST.L D3 ;right to left? stb BMI.S @1 ;if so, skip stb CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? stb BEQ rTransparent8 ;yes, go use quickdraw stb ; if it is, go use Andy’s QuickerDraw special 8-bit case ; which doesn’t have this problem stb @1: LEA @RealrTransparent,A0; this fixes a bug that the optimization introduced stb MOVE.L A0,ModeCase(A6) ; which was causing the loss of pattern data stb @RealrTransparent MOVE patHMask(A6),D1 ;set up source constriction MOVE pixInLong1(A6),A0 ;set up absolute long bump MOVE longBump(A6),A2 ;set up long bump BFEXTU D5{0:D7},D0 MOVE.L D0,A1 ;set up pixel of background @loopTop AND D1,D6 ;constrict to the source long if in a pattern mode BFEXTU (A4){D4:D7},D0 ;a pixel of the mask BEQ.S @skip BFEXTU (A3){D6:D7},D0 ;get a pixel of the source (zeros top word) CMP.L D0,A1 ;same as a pixel of the background? BEQ.S @skip BFINS D0,(A5){D4:D7} ;move to the destination @skip ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L D3,D4 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = scanCount ; a2 = d2 = run cnt ; a3 = srcPtr/patPtr d3 = ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = backColor ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rTransparent32 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag @blit move.l 0(a0,d6),d7 ;get src pixel add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode cmp.l d7,d5 ;is src backColor? beq.s @skip1 ;yes, don't write to dst MOVE.L d7,(a5) ;write pattern to dest @skip1 add a4,a5 ;bump dst ptr DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = maskPtr d1 = scanCount ; a2 = d2 = run cnt ; a3 = srcPtr/patPtr d3 = ; a4 = hBump d4 = patHMask ; a5 = dstPtr d5 = backColor ; a6 = locals d6 = pattern offset ; a7 = d7 = src pixel ;------------------------------------------------------- rTransparent16 move.l a3,a0 ;set up srcAddr move.l runBuf(a6),A1 ;point to run encoded mask buffer @inst move.l (a1)+,d2 ;pick up next instruction long bmi.s NxtNewSrc32 add.w d2,a5 ;bump destptr by skip amount add.w d2,d6 ;BUMP src/pattern index and.w d4,d6 ;constrict to the source long if in a pattern mode swap d2 ;get mask/blit cnt and check done flag bclr #runMaskBit-16,d2 ;check and clear mask flag beq.s @blit ;no mask, so go fast @mask tst.l (a1)+ ;examine mask bmi.s @first ;blit only first word move.w 2(a0,d6.w),d7 ;get src pixel cmp.w d7,d5 ;is it backcolor? beq.s @skip1 ;yes, ignore it move.w d7,2(a5) ;write pattern to dest @skip1 add a4,a5 ;bump dst ptr add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @first move.w 0(a0,d6.w),d7 ;get src pixel cmp.w d7,d5 ;is it backcolor? beq.s @skip2 ;yes, ignore it move.w d7,(a5) ;write pattern to dest @skip2 add a4,a5 ;bump dst ptr add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@mask ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs @blit move.l 0(a0,d6.w),d7 ;get 2 src pixels cmp.l d7,d5 ;is it backcolor? beq.s @skip3 ;yes, ignore it cmp.w d7,d5 ;check pixel 2 beq.s @skip4 ;yes, skip it move.w d7,2(a5) ;write pixel 2 to dest @skip4 swap d7 ;get first pixel cmp.w d7,d5 ;check pixel 1 beq.s @skip3 ;yes, skip it move.w d7,(a5) ;write only first pixel to dest @skip3 add a4,a5 ;bump dst ptr add a4,d6 ;bump src index and.w d4,d6 ;constrict to the source long if in a pattern mode DBRA D2,@blit ;LOOP ALL LONGS THIS ROW BRA.s @inst ;LOOP BACK FOR more runs ENDPROC