; ; File: BitBlt.a ; ; Function: Low-level bit boundary block transfer. ; ; OLD NOTE: Because BitBlt only called by RgnBlt, we know that the ; bitMaps that are passed us are not portBits. ; ; Copyright: © 1981-1990, 1992 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 12/2/92 kc Roll in CopyBits changes from QuickDrawPatches.a in Reality ; 10/2/92 SAH Fixed a word alignment bug in the fast bSetup0 and bSetup8 ; patches (word alignment would cause the Move16 code to fail). ; Also added a check in the bSetup8 patch to make sure that the ; left edge quadlong alignment would remain constant across ; scanlines. ; 10/1/92 SAH Brought in fast bSetup8 patch for 040 machines that uses ; Move16's. ; 4/10/92 SAH Moved in the working fast bSetup0 patch for 68040 machines from ; QDIIciPatchROM.a. ; 7/30/92 chp Moved a short branch inside the conditional generated by ; to get rid of an assembler “trivial short branch = NOP” warning. ; 7/1/92 kc Conditionalize the Move16 code in bSetup0 because it doesn't ; work without flushing the cache. ; 6/12/92 stb stb Synched-up with QDciPatchROM.a; added comments ; from QDciPatchROM.a; alpha channel stuff at bLONG8, bSETUP8, ; bXLONG8, bXMAIN8, bSubOver16; handle vertically aligned hilites ; and preserve a non-white bkg color through the entire blit at ; bSloHilite; fixed bTransparent and rTransparent to remove an ; optimization that was losing pattern data. Related changes in ; Arith8Blt.a; ; <17> 6/11/91 gbm Take out conditional for Regatta ; <16> 3/13/91 SMC forRegattaCPUs, fixed cpuFlag check in bSetup0 to include '040 ; processors and greater. ; <15> 12/13/90 SMC Pulled out Debugger traps left in <14>. With KON. ; <14> 11/26/90 SMC Fixed pattern hiliting once and for all. With BAL. ; <13> 10/31/90 SMC Fixed alpha channel crimes with BAL. ; <12> 10/18/90 SMC Simplify and shorten colorized OR and BIC blit loops. With KON. ; <11> 9/26/90 SMC Fixed right edge problem in bSubOver16. A move.l was being used ; to retrieve a 16-bit pixel instead of a move.w. ; <10> 9/26/90 SMC Removed bTransparent optimization that was losing pattern data. ; <9> 9/17/90 BG Removed <5>. 040s are now behaving more reliably. ; <8> 9/13/90 SMC Fixed problem in bSloHilite when the background color is not ; white. ; <7> 8/17/90 KON Fix vertically aligned, horizontally overlapped arithmetic ; transfer modes. The pixel location was saved as a word instead ; of a long (in bAvg), and there was an alignment problem. This ; will not be fixed on the ci to save space. ; <6> 8/13/90 SMC Made speed improvements to bMAIN0,1,2,3 and bcMain0,3. ; <5> 6/25/90 BG Added EclipseNOPs for flakey 040s. ; <4> 6/5/90 KON Add check for inverting; if so, goto NotFast. ; <3> 6/4/90 KON Check of modeCase colorizing was backwards. ; <2> 5/24/90 KON Make bitblt look at colorizing flags rather than BGnotWhite. ; <1.7> 11/18/89 BAL Added QuickerDraw 8-bit arithmetic transfer loops ; <•1.6> 7/14/89 BAL For Aurora: Final CQD ; <1.5> 6/30/89 BAL Unrolled loop to get a 2x improvement in big-pattern filling ; <•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 ; 9/18/88 BAL Altered to use common stack frame file 'Drawing Vars.a' ; 1/3/87 CRC added color blt loops ; 12/12/86 CRC Added arithmetic modes ; 7/29/86 EHB Use new stack-based EXPAT buffer ; 7/26/86 EHB Added support for expanded patterns ; 7/22/86 EHB Added color to pattern OR and pattern BIC transfer modes Added ; FIRSTMASK to stack frame to free up a register ; 6/22/86 EHB Add FCOLOR, BCOLOR params to BitBlt Call new PatExpand with ; FCOLOR, BCOLOR ; 6/19/86 EHB Modified to use pixel depth All horizontal calculations done ; using longs for big pixels ; 6/9/86 EHB Use new LMask32 and RMask32 routines ; 6/8/86 EHB Modified bitBlt and scanline routines to use longs and BFEXTU. ; 6/24/85 EHB Big re-org: all shared fields set up by stretchbits before ; calling here. All parms in stack frame or registers. ; ; To Do: ; BLANKS ON STRING ASIS MACHINE MC68020 BITBLT PROC EXPORT EXPORT bMAIN0, bMAIN1, bMAIN2, bMAIN3, bSETUP8, bMAIN9, bSETUP10, bMAIN11 EXPORT bXMAIN8, bXMAIN9, bXMAIN10, bXMAIN11, bcMain0, bcMain1, bHilite, bcMain3 EXPORT bEND0, bEND1, bEND2, bEND3, bLONG8, bEND9, bEND10, bEND11, bXLONG8, bXEND9 EXPORT bXEND10, bXEND11, bcEnd0, bcEnd1, bSloHilite, bcEnd3, bAvg, bAddPin, bAddOver EXPORT bSubPin, bTransparent, bMax, bSubOver, bMin, bLeft0, bSetup0 EXPORT bArith32Setup,bArith16Setup,bArith32Tab,bArith16Tab,bHiliteTab ;-------------------------------------------------------------- ; ; PROCEDURE BitBlt(srcPix,dstPix: BitMap; ; srcRect,dstRect: Rect; ; mode: INTEGER; pat: Pattern); ; ; ALL PARAMETERS PASSED IN STACK FRAME. ; ; TRANSFERS A RECTANGULAR BLOCK OF BITS WITH NO CLIPPING AT ALL. ; MODE SPECIFIES THE COMBINATION MODE AND WHETHER THE SOURCE SHOULD COME ; FROM THE SOURCE BITMAP OR FROM A REPEATING PATTERN. ; ; COPYRIGHT APPLE COMPUTER INC. ; WRITTEN BY BILL ATKINSON ; ; POSITION INDEPENDENT AND RE-ENTRANT, CLOBBERS ONLY A0. ; ; mode bit meaning ; 7 6 5 4 3 2 1 0 ; 0 msk ari 0 pat not coxb- ; arith.vars ; ; 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 --- ; 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 --- ; 50 src Hilite Dst (bg <--> fg) ; 51 --- ; 52 … 55 unassigned ; 56 --- ; 57 --- ; 58 pat Hilite Dst ; Note that the mask bit is stripped by DrawText ;---------------------------------------------------- ; ; STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS. ; ; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK: ; ; STACK FRAME VARS USED BY SEEKMASK (CALLED BY STRETCHBITS, RGNBLT, DRAWARC, DRAWLINE) ; ;---------------------------------------------------- ; ; 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 nonblack/white colors blit32 EQU 0 ;<14> ;---------------------------------------------------- ; ; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK: ; ; STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS. ; &CurFile SETC 'BITBLT' INCLUDE 'DrawingVars.a' ;------------------------------------------------------------- ; ; ENTER HERE. CALLER TAKES CARE OF CURSOR. ; ; ON ENTRY, REGISTERS SET UP LIKE THIS: ; ; A2: SRCRECT ; A3: DSTRECT ; A4: SRCPIX ; A5: DSTPIX ; ; D3: SRCSHIFT (NOT USED) ; D4: DSTSHIFT ; D7: INVERT FLAG ; ; ONLY A6,A7 MUST BE PRESERVED ;---------------------------------------------------- ; ; FIRST CLIP SRCRECT TO MATCH MINRECT. (COPY SRCRECT SINCE IT'S NOT VAR) ; ONLY TOPLEFT USED. ; LEA SRCRECT2(A6),A0 ;POINT TO LOCAL COPY OF SRCRECT MOVE MINRECT+TOP(A6),D0 ;GET MINRECT TOP SUB TOP(A3),D0 ;CONVERT FROM DST COORDS ADD TOP(A2),D0 ;TO SRC COORDS MOVE D0,TOP(A0) ;PUT CLIPPED SRC TOP INTO COPY MOVE MINRECT+LEFT(A6),D0 ;GET MINRECT LEFT SUB LEFT(A3),D0 ;CONVERT FROM DST COORDS ADD LEFT(A2),D0 ;TO SRC COORDS MOVE D0,LEFT(A0) ;PUT CLIPPED SRC LEFT INTO COPY MOVE.L A0,A2 ;KEEP NEW SRCRECT PTR IN A2 LEA MINRECT(A6),A3 ;AND USE MINRECT AS DSTRECT ;------------------------------------------------------------- ; ; CALC HEIGHT OF DSTRECT. QUIT IF HEIGHT <= 0 ; MOVE BOTTOM(A3),D0 ;GET BOTTOM SUB TOP(A3),D0 ;CALC HEIGHT BLE GOHOME ;QUIT IF HEIGHT <= 0 MOVE D0,HEIGHT(A6) ;SAVE FOR LATER ;-------------------------------------------------------------- ; ; SET UP FOR TOP TO BOTTOM, LEFT TO RIGHT ; GET SRC AND DST TOP ; MOVE #4,D3 ;BUMP:=4 (TRANSFER LEFT TO RIGHT) MOVE TOP(A2),D0 ;GET SRC TOP SUB BOUNDS+TOP(A4),D0 ;CONVERT SRC TOP TO GLOBAL MOVE D0,SRCV(A6) ;SAVE FOR LATER MOVE TOP(A3),D0 ;GET DST TOP SUB BOUNDS+TOP(A5),D0 ;CONVERT DST TOP TO GLOBAL MOVE D0,DSTV(A6) ;SAVE FOR LATER ;------------------------------------------------- ; ; SET UP DRAWING PARAMETERS FOR PATTERNS ; MOVE LOCMODE(A6),D2 ;GET MODE BTST #3,D2 ;PATTERN BIT SET? BEQ.S USESRC ;=>NO, USE SOURCE MOVE PATROW(A6),D1 ;BIG PATTERN USED? BNE.S DONEW ;=>YES, GO USE IT MOVEQ #$F,D7 ;TREAT COORD MOD 16 AND TOP(A3),D7 ;GET DST TOP LOCAL COORD MOVE.L ([EXPAT,A6],D7*4),D6 ;GET FIRST PATTERN DATA BRA NOTSRC ;NOT USING SRC, SKIP OVER ; NEW PATTERN. SET STARTING VERT POSITION, SET FLAG. DONEW 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 TOP(A3),D6 ;GET TOP VERT COORD MULU D1,D6 ;GET PATVPOS INTO D6 MOVE PATHMASK(A6),D7 ;SET UP HMASK IN D7 BRA NOTSRC ;NOT USING SRC, SKIP OVER ;----------------------------------------------------------- ; ; SOURCE WILL BE USED, SO SET UP VERT AND HORIZ DIRECTIONS ; SUCH THAT SRC WON'T GET CLOBBERED TILL AFTER IT HAS BEEN USED ; USESRC MOVE.L BASEADDR(A4),D0 ;GET SRC BASEADDR CMP.L BASEADDR(A5),D0 ;ARE SRC AND DST ARRAYS THE SAME ? BNE.S GETSRC ;NO, DONT WORRY ABOUT OVERLAP MOVE SRCV(A6),D0 ;GET SRCV CMP DSTV(A6),D0 ;IS SRCV > DSTV ? BGT.S GETSRC ;YES, CONTINUE WITH TOP TO BOTTOM BLT.S UPSIDE ;NO, DO UPSIDE DOWN MOVE LEFT(A2),D0 ;SAME VERT, CHOOSE HORIZ DIRECTION SUB BOUNDS+LEFT(A4),D0 ;CONVERT SRC LEFT TO GLOBAL MOVE LEFT(A3),D1 ;GET DST LEFT SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL CMP D1,D0 ;IS SRCLEFT < DSTLEFT ? BGE.S GETSRC ;NO, DO LEFT TO RIGHT move minRect+right(A6),d2 ;get local srcRight sub minRect+left(A6),d2 ;get src width add d0,d2 ;get global srcRight cmp d1,d2 ;is srcRight < dstLeft ? ble.s GETSRC ;yes, no overlap NEG D3 ;no, BUMP:=-4 (RIGHT TO LEFT) BRA.S GETSRC ;CONTINUE ;---------------------------------------------------------- ; ; DO UPSIDE DOWN TO AVOID CLOBBERING SRC ; UPSIDE MOVE HEIGHT(A6),D0 ;GET HEIGHT SUB #1,D0 ;CALC HEIGHT-1 ADD D0,SRCV(A6) ;SRCVERT:=SRCV+HEIGHT-1 ADD D0,DSTV(A6) ;DSTVERT:=DSTV+HEIGHT-1 NEG.L SRCROW(A6) ;SRCROW:=-SRCROW NEG.L DSTROW(A6) ;DSTROW:=-DSTROW ;----------------------------------------------------- ; ; SET UP SHIFTCNT IN D6 (RELATIVE SHIFT BETWEEN SRC & DST) ; GETSRC MOVE LEFT(A3),D6 ;GET DST LEFT SUB BOUNDS+LEFT(A5),D6 ;CONVERT TO GLOBAL EXT.L D6 ;MAKE IT A LONG LSL.L D4,D6 ;CONVERT DST PIXELS TO BITS MOVE LEFT(A2),D1 ;GET SRC LEFT SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL EXT.L D1 ;MAKE IT A LONG MOVE SRCSHIFT(A6),D0 ;GET DEPTH OF SRC PIXELS LSL.L D0,D1 ;CONVERT PIXELS TO BITS SUB.L D1,D6 ;CALC DELTA HORIZ MOVEQ #$1F,D0 ;NEED DELTA HORIZ MOD 32 AND.L D0,D6 ;SHIFTCNT:=DELTA HORIZ MOD 32 NEG.L D6 ;NEGATE FOR USE WITH BFEXTU ;------------------------------------------------------------ ; ; SET UP SRCLEFT IN A4, ADDR OF LEFTMOST SRC LONG ; (GOODBYE SRCPIX PTR) ; MOVE ROWBYTES(A4),D0 ;GET SRC ROWBYTES AND #NURBMASK,D0 ;MASK OFF FLAG BITS MULS SRCV(A6),D0 ;CALC SRC ROWBYTES * FIRST SRC VERT; BAL 02Dec88 MOVE.L BASEADDR(A4),A4 ;GET START OF SRC BITMAP ADD.L D0,A4 ;ADD TO BITMAP START SUB.L D6,D1 ;CALC SRCH+SHIFTCNT ASR.L #5,D1 ;CONVERT BITS TO LONGS ADD.L D1,D1 ;CONVERT LONGS TO WORDS ADD.L D1,D1 ;CONVERT WORDS TO BYTES ADD.L D1,A4 ;LEAVE SRCLEFT IN A4 ;------------------------------------------------------------ ; ; SET UP DSTLEFT IN A5, ADDR OF LEFTMOST DST LONG ; (GOODBYE DSTPIX PTR) ; NOTSRC MOVE LEFT(A3),D1 ;GET DST LEFT SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL EXT.L D1 ;MAKE IT LONG LSL.L D4,D1 ;CONVERT PIXELS TO BITS MOVE ROWBYTES(A5),D0 ;GET DST ROWBYTES AND #NURBMASK,D0 ;MASK OFF FLAG BITS MULS DSTV(A6),D0 ;CALC DSTROW * FIRST DST VERT; BAL 02Dec88 MOVE.L BASEADDR(A5),A5 ;GET START OF DST BITMAP ADD.L D0,A5 ;ADD DSTV*DSTROW MOVE.L D1,D0 ;COPY DSTLEFT GLOBAL ASR.L #5,D1 ;CONVERT BITS TO LONGS LSL.L #2,D1 ;CONVERT LONGS TO BYTES ADD.L D1,A5 ;GET DSTLEFT IN A5 ;------------------------------------ ; ; SET UP D6 FOR BIG PATTERNS (PATVPOS IN HIGH WORD, PATHPOS IN LOW WORD) ; SET UP A4 TO POINT TO FIRST SCAN IN PAT TO BE USED ; TST PATROW(A6) ;DOING BIG PATTERN? BEQ.S NOTBIGPAT ;=>NO MOVE.L EXPAT(A6),A4 ;SRCADDR := EXPANDED PATTERN ADD D6,A4 ;ADD PATVPOS TO PATTERN SWAP D6 ;SAVE PATVPOS IN HIGH WORD MOVE D1,D6 ;GET LOW WORD OF DSTLEFT AND D7,D6 ;MASK FOR HORIZ OFFSET INTO PATTERN MOVE D6,PATHPOS(A6) ;AND SAVE STARTING HORIZ OFFSET NOTBIGPAT ;------------------------------------- ; ; SET UP 32 BIT LEFTMASK IN D4 ; MOVE.L D4,D5 ;SAVE DSTSHIFT FOR LEFTMASK MOVEQ #$1F,D2 ;NEED LEFT AND RIGHT MOD 32 AND.L D2,D0 ;GET DSTH MOD 32 MOVEQ #-1,D4 ;GET ALL ONES INTO LEFTMASK LSR.L D0,D4 ;SHIFT IN ZEROS FROM LEFT ;------------------------------------- ; ; SET UP 32 BIT RIGHTMASK IN D5 ; (GOODBYE DSTSHIFT) ; MOVE RIGHT(A3),D1 ;GET DST RIGHT SUB LEFT(A3),D1 ;CALC WIDTH BLE GOHOME ;QUIT IF WIDTH <= 0 move.w d1,destPixCnt(a6) ;save for 16/32 bit arith loops EXT.L D1 ;MAKE WIDTH LONG LSL.L D5,D1 ;CONVERT PIXELS TO BITS ADD.L D0,D1 ;CALC (DSTH MOD 32) + WIDTH MOVEQ #-1,D5 ;GET ALL ONES IN RIGHTMASK AND.L D1,D2 ;GET RIGHT MOD 32 beq.s @maskOK ;mask ok if width is mult of 32 <1.5> BAL LSR.L D2,D5 ;SHIFT IN ZEROS FROM LEFT NOT.L D5 ;AND NEGATE TO MAKE RIGHTMASK @maskOK ;------------------------------------------------ ; ; CALC TOTAL NUMBER OF DST LONGS-1 ; subq.l #1,d1 ;force multiples of 32 to round down <1.5> BAL ASR.L #5,D1 ;CALC ((DSTH MOD 32)+WIDTH) DIV 32 MOVE D1,LONGCNT(A6) ;SAVE AS LONGCNT MOVE.L D1,D2 ;COPY FOR BELOW ;------------------------------------------------ ; ; SET UP SRCBUMP AND DSTBUMP, ASSUMING BUMPING TO THE RIGHT ; ADD.L D1,D1 ;CONVERT LONGS TO WORDS ADD.L D1,D1 ;CONVERT WORDS TO BYTES MOVE.L D1,D0 ;COPY FOR BELOW ADDQ.L #4,D0 ;ADJUST FOR TOTAL BYTES NEEDED ;-------------------------------------------------------------------------- ; ; IF DRAWING BACKWARDS FROM RIGHT, THEN ADJUST DSTBUMP, ; ADJUST SRCADDR,DSTADDR TO FIRST LONG, ; AND SWAP LEFT AND RIGHT MASKS FOR FIRSTMASK AND LASTMASK. ; MOVE D3,A0 ;put hBump (+-4) into A0 TST D3 ;ARE WE STARTING ON THE LEFT ? BPL.S DIROK ;YES, CONTINUE NEG.L D0 ;calc -1 * bytesNeeded ADD.L D1,A5 ;ADJUST DSTADDR TO RIGHTMOST ADD.L D1,A4 ;ADJUST SRCADDR TO RIGHTMOST EXG D4,D5 ;FIRSTMASK=RIGHT,LASTMASK=LEFT DIROK MOVE srcRow+2(A6),srcBump(A6) SUB D0,srcBump(A6) ;srcBump := srcRow +- bytesBumped MOVE dstRow+2(A6),A3 SUB D0,A3 ;dstBump := dstRow +- bytesBumped ;---------------------------------------------- ; ; SET UP MODE CASE JUMP IN A1 ; ; D6 has bit shiftCnt ; D4 has firstMask ; D2 has longCnt ; GETMODE MOVE LOCMODE(A6),D0 ;GET TRANSFER MODE BNE.S NOTFAST ;BR IF NOT MODE 0 ScaleColorBit EQU 3 SwapFGBGBit EQU 4 UseStretchBit EQU 5 InvertItBit EQU 7 ColorizeInModeCaseBit EQU 8 ColorizeInSrcBufBit EQU 9 BTST #ColorizeInModeCaseBit, XLateFlag(a6) ;colorize? BNE.S NOTFAST ;no, continue tst.l d7 ;inverting? bne.s NOTFAST ;yes, go slow move d6,d1 ;get shiftCnt and #7,d1 ;multiple of 8? BNE.S NOTFAST ;NO, CONTINUE TST D2 ;IS LONGCNT > 0 ? BLE.S NOTFAST ;NO, CONTINUE move.w d6,d1 ;get shiftCnt asr.w #3,d1 ;get src adjustment in bytes add d1,a4 ;misAlign src @Fast MOVE.L BitBltSetup0,A1 ;USE FAST COPY. (get address from trap table) TST D3 ;ARE WE BUMPING LEFT TO RIGHT ? BPL.s @goFast ;YES, ALL SET MOVE.L BitBltLeft0,A1 ;NO, USE BACKWARDS LOOP (get address from trap table) @goFast jmp (A1) NOTFAST CMP #$20,D0 ;a new arithmetic mode? BLO @notHilite ;if 0 to 1F, it is an old mode or old mode + big pat ; change bColor to transColor (the unmapped background color) since bColor is used in ; arithmetic transfer modes to compare with, not to apply to the source MOVE.L transColor(A6),bColor(A6) CMP #$40,D0 BHS goHome ;an undefined mode; do nothing CMP #$30,D0 BLT.S @arithMode CMP #$32,D0 ;source hilite? BEQ.S @arithMode ;treat like an arithmetic mode CMP #$3A,D0 ;pat hilite? BNE goHome ;if not, an undefined mode ; if the pattern is black & mode is hilite, then go to fast hilite case TST patRow(A6) ;big or small? BNE.S @arithMode ;if big, assume it is not all black ;check all longs of the small pattern for blackness MOVE.L BCOLOR(A6),D2 ;check for non-background color <14> MOVEQ #$0F,D3 ;16 longs in a pattern MOVE.L EXPAT(A6),A1 ;pointer to first long @nextLong CMP.L (A1)+,D2 ;is it black? DBEQ D3,@nextLong ;check all of the pattern for black <14> BNE @fastHilite ;if all black, do fast way <14> @arithMode BTST #3,D0 ;is the pattern bit set? BEQ.S @newSource ;if a source mode, set up registers appropriately MOVE patRow(A6),D2 ;if patRow contains appropriate value, set big pat bit BEQ.S @smallPattern ; big pattern case @bigPat MOVE.B #1,endSwitch(A6) ;note that this is a big pattern (make it positive) SWAP D6 MOVE D6,patPos(A6) ;set up large pattern vertical offset 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 dstPix+pixelSize(A6),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 ASL #3,D2 ;convert from bytes to bits SUBQ #1,D2 ;make it a mask AND D3,D2 ;force pixel alignment MOVE D2,patHMask(A6) ;save mask BRA.S @skipSourceSetup ; small pattern case @smallPattern CLR.B endSwitch(A6) ;note that this is a small pattern mode LEA ([EXPAT,A6],D7*4),A4 ;GET FIRST PATTERN DATA 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 @skipSourceSetup ; source case @newSource ST endSwitch(A6) ;note that this is a source mode (make it negative) MOVE #-1,patHMask(A6) ;do not restrict source range if mode is source @skipSourceSetup AND #$37,D0 ;ignore the pattern info ; add, add pin, sub, sub pin, max, min, avg registers and locals set up ; D0 dest/mask pixel off. D1 jump table offset D2 pixels in long (or 0 if 1 long) ; D3 (fg long) D4 (bg long) D5 inverse color table entry size ; D6 source pixel offset D7 bits per pixel A0 inverse color table ; A1 color table A2 long bump A3 background pixel ; A4 (source) A5 (destination) ; (SP) hbump for a pixel doneMid(A6) flags lastMask(A6) (right mask if left to right) ; midCount(A6) pixel cnt pixInLong(A6) pixels in a long ; invSize(A6) inverse color table resolution longCnt(A6) same as D2 MOVEQ #32,D2 ;bits in a long MOVEQ #0,D7 MOVE dstPix+pixelSize(A6),D7 ;get number of bits in a pixel DIVU D7,D2 ;figure number of pixels in a long MOVE D2,pixInLong(A6) ;save for later multiply MOVE D2,pixInLong1(A6) ;left 1 based for transparent long case MOVEQ #0,D3 ;assume destination offset is 0 MOVE.L D7,-(SP) ;assume bump is positive MOVEQ #32,D1 ;positive long bump for transparent move.w a0,hBump(a6) ;save in stack frame for direct loops CMP #0,A0 ;bumping postive or negative? BPL.S @bumpOK NEG.L (SP) ;make pixel bump negative NEG.L D1 ;make long bump negative MOVEQ #32,D3 SUB D2,D3 ADD.L D3,D6 ;D6 set to first source pixel position @bumpOK MOVE.L D1,A2 ;set up long bump for transparent MOVE.L D5,lastMask(A6) ;free up a register MOVE.L invColor(A6),A0 ;set up pointer to inverse color table in register MOVE invSize(A6),D5 ;set up resolution of inverse color table in register CLR.B doneMid(A6) ;set up loop/mask flags MOVE longCnt(A6),D1 ;0 if only 1 long SUBQ #1,D1 ;less 1 more for last long MOVE D1,longCnt(A6) ;assume all fits in 1 long BMI.S @only1Long ;if only one long, set long count to -1 MULU pixInLong(A6),D1 ;convert long count to pixel count SUBQ #1,D1 ;make count 0 based for DBRA MOVE D1,midCount(A6) ;save number of pixels in middle part less first, last masks SUBQ #1,D2 ;make count 0 based for DBRAs MOVE D2,longCnt(A6) ;save # of pixels in a mask in long count @only1Long SUBQ #1,pixInLong(A6) ;make count 0 based for DBRAs MOVE.l D3,destPixOffset(A6) ;save as a long <08Jan89 BAL> CMP #$30,D0 ;hilite? BGT.S @slowHilite ;if so, set up things a little different for hilite if Quicker THEN cmp.w #8,d7 ;is pixelsize >= 8? <1.7> BAL bge.s @FastDeepArith ;yes, handle direct arith loops separately <1.7> BAL else cmp.w #16,d7 ;is pixelsize >= 16? <1.7> BAL bge.s @FastDeepArith ;yes, handle direct arith loops separately <1.7> BAL endif @notFastArith ; <1.7> BAL ADD D0,D0 ;make it a word offset (40 … 4E) MOVE D0,D1 ;set up in offset register for jump table, below BFEXTU transColor(A6){0:D7},D0 ;get 1 pixel of the background color for transparent MOVE.L D0,A3 ;register set up for transparent MOVE.l D3,D0 ;set up destination offset BRA doMain ; @slowHilite MOVE.l D3,D0 ;set up destination offset MOVEQ #$3C,D1 ;hilite jumptable offset for slow case BFEXTU hilitColor(A6){0:D7},D5 ;set up a pixel of the hilite color BRA doMain ; ———————————————————————————————————————————————————————————————————————————————————————— ; highlight registers and locals set up ; D0 background pixel D5 foreground pixel D7 pixel size A0 foreground long ; A2 32-pixel size lastMask(A6) @fastHilite MOVE dstPix+pixelSize(A6),D7 ;width of a pixel MOVE.L D5,lastMask(A6) ;free up a register MOVE.L hilitColor(A6),A0 ;set up a long of the forecolor BFEXTU hilitColor(A6){0:D7},D5 ;set up a pixel of the forecolor LEA 32,A2 SUB D7,A2 ;set up constant equal to long width in bits - pixel width BFEXTU transColor(A6){0:D7},D0 ;get 1 pixel of the background color for hilite move.w dstShift(a6),d1 ;get shift count MOVE.L bHiliteTabPtr,A1 ;get address of table (from trap table) ADD.L -4(a1,D1*4),a1 ;select routine based on destination depth BRA NEXTROW @FastDeepArith ;enter with mode in d0 and.w #$7,d0 ;strip arithmetic bit beq.s @DirectAvg ;it's blend mode, so check for 50% case @modeOK if blit32 then ;<14> cmp.w #16,d7 ;is dst 16 bits/pixel? beq.s @Arith16 ;use alternate table if Quicker THEN blt.s @Arith8 ;use alternate table <1.7> BAL endif move.l bArith32TabPtr,A1 ;point to 32 bit/pixel loops add.l (a1,d0*4),a1 ;get modecase based on d0 _bArith32jmp @Arith16 move.l bArith16TabPtr,A1 ;point to 16 bit/pixel loops add.l (a1,d0*4),a1 ;get modecase based on d0 MOVE.L D4,D1 ;remember FIRSTMASK _bArith16jmp endif ;<14> @Arith8 if Quicker THEN cmp.w #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? bne.s @notFastArith ;if not, skip tst.l (sp) ;right to left? bmi.s @notFastArith ;if so, skip lea bArith8Tab,A1 ;point to 8 bit/pixel loops add.l (a1,d0*4),a1 ;get modecase based on d0 move.l D4,D1 ;remember FIRSTMASK bra.s NextRow endif @DirectAvg lea weight(a6),a1 ;point to weights move.w (a1)+,d1 cmp.w (a1)+,d1 ;is opColor gray? bne.s @modeOK cmp.w (a1),d1 bne.s @modeOK addq #1,d1 ;yes, check for gray values of $8000 or $7fff and.w #$fffe,d1 cmp.w #$8000,d1 bne.s @modeOK addq #8,d0 ;use alternate modecase bra.s @modeOK @notHilite AND #$B,D0 ;TREAT MODE MOD 16 AND KILL INVERT BIT MOVE D0,D1 ;MAKE A COPY AND #3,D0 ;MASK FOR LOW BITS ONLY ADD D0,D1 ;MAKE MODIFIED MODE * 2 FOR INDEX CMP #8,D1 ;pattern? BGE.S @checkBigPat ;don’t worry about color src blt loops if so CMP #4,D1 ;xor? BEQ.S @0 ;skip if so btst #ColorizeInModeCaseBit, XLateFlag(a6) ;colorize? beq.s @0 ;use color loops only if colorize ADD #$18,D1 ;use color loops @checkBigPat TST PATROW(A6) ;BIG PATTERN? BEQ.S @0 ;=>NO, CHECK FOR ONE LONG ADD #8,D1 ;YES, BUMP INDEX @0 TST D2 ;IS DST ALL IN ONE LONG ? BNE.S DOMAIN ;=>NO, USE FIRST JUMP TABLE ADD #$20,D1 ;YES, USE SECOND JUMP TABLE DOMAIN LEA BitBltModeTab,A1 ;GET ADDRESS OF MODE TABLE MOVE.L 0(A1,D1*2),A1 ;POINT TO THIS MODE'S ROW LOOP ;--------------------------------------------------------- ; ; OUTER LOOP: DO EACH SCAN LINE AND COME BACK TO NXTSRC OR NXTPAT. ; SOME MODES OPTIMIZE AND DO WHOLE OUTER LOOP AND COME BACK TO GOHOME. ; NEXTROW MOVE.L D4,FIRSTMASK(A6) ;SAVE FIRSTMASK MOVE.L FCOLOR(A6),D3 ;GET FGCOLOR MOVE.L BCOLOR(A6),D4 ;GET BKCOLOR (transColor if arithmetic mode) BRA.S ROWLOOP ;SKIP TO FIRST ROW CASE NXTSRC ADD SRCBUMP(A6),A4 ;BUMP SRCPTR TO NEXT ROW ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT BEQ.S GOHOME ;QUIT IF LAST SRC DONE ROWLOOP MOVE.L FIRSTMASK(A6),D1 ;MASK:=FIRSTMASK MOVE LONGCNT(A6),D2 ;GET LONGCOUNT JMP (A1) ;DO THIS ROW AND COME BACK NXTBIGPAT clr.w d6 ;make it unsigned SWAP D6 ;GET VERT POSITION IN PATTERN SUB.l D6,A4 ;GET BACK PAT BASE ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ADD.l D6,A4 ;BUMP TO PROPER VERT SWAP D6 ;SAVE VERTICAL POSITION MOVE PATHPOS(A6),D6 ;INIT HORIZONTAL OFFSET ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT BNE.S ROWLOOP ;LOOP FOR ALL SRCROWS GOHOME RTS ;THEN QUIT NXTPAT ADD #1,D7 ;BUMP PATTERN SELECTOR AND #$0F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L ([EXPAT,A6],D7*4),D6 ;GET FIRST PATTERN DATA ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT BNE.S ROWLOOP ;LOOP FOR ALL SRCROWS RTS ;THEN QUIT if blit32 then ;<14> NxtNewSrc32 TST.B endSwitch(A6) BEQ.S NxtNewPat BPL.S NxtNewBigPat ADD SRCBUMP(A6),A4 ;BUMP SRCPTR TO NEXT ROW ; moveq #0,d6 ;clear out position index MOVE.L patOffset(A6),d6 ;reset to left edge BRA.S newCommon endif ;<14> NxtNewSrc TST.B endSwitch(A6) BEQ.S NxtNewPat BPL.S NxtNewBigPat ADD SRCBUMP(A6),A4 ;BUMP SRCPTR TO NEXT ROW BRA.S newCommon NxtNewBigPat moveq #0,d0 ;clear out high word MOVE PatPos(A6),D6 ;GET VERT POSITION IN PATTERN SUB.l D6,A4 ;GET BACK PAT BASE ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ADD.l D6,A4 ;BUMP TO PROPER VERT MOVE D6,PatPos(A6) ;SAVE VERTICAL POSITION BRA.S newPatCommon NxtNewPat MOVE PatPos(A6),D1 ;was in D7; set up from locals for new modes ADD #1,D1 ;BUMP PATTERN SELECTOR AND #$0F,D1 ;MOD 16 FOR 16 LONG REPEAT MOVE D1,PatPos(A6) ;save for new modes LEA ([EXPAT,A6],D1*4),A4 ;GET FIRST PATTERN DATA newPatCommon MOVE.L patOffset(A6),D6 ;initialize 1 pixel to the left of pat if left to right newCommon CLR.B doneMid(A6) ;set up loop/mask flags MOVE.l destPixOffset(A6),D0 ;set up destination pixel offset ADD dstRow+2(A6),A5 SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT BNE.S ROWLOOP ;LOOP FOR ALL SRCROWS ADDQ #4,SP ;toss hbump on stack RTS ;THEN QUIT ;---------------------------------------------------------------; ; ; ; INTERFACE TO EACH BITBLT SCANLINE LOOP: ; ; ; ; REGISTERS: A0: hBump (+-4) D0: scratch ; ; A1: MODE CASE JUMP D1: FIRSTMASK.L ; ; A2: used for loop jmp D2: LONGCNT ; ; A3: dstBump D3: FG COLOR ; ; A4: SRCPTR D4: BK COLOR ; ; A5: DSTPTR D5: LASTMASK.L ; ; A6: LOCALS D6: SHIFTCNT OR PATTERN ; ; A7: STACK PTR D7: INVERT OR PAT-SEL ; ; ; ;---------------------------------------------------------------; IF 0 THEN MODETAB DC.W MAIN0-MODETAB ;0 JUMP TABLE USED IF DST WIDER THAN ONE LONG DC.W MAIN1-MODETAB ;2 DC.W MAIN2-MODETAB ;4 DC.W MAIN3-MODETAB ;6 DC.W SETUP8-MODETAB ;8 DC.W MAIN9-MODETAB ;A DC.W SETUP10-MODETAB ;C DC.W MAIN11-MODETAB ;E DC.W XMAIN8-MODETAB ;10 EXPANDED PATTERN MODES DC.W XMAIN9-MODETAB ;12 DC.W XMAIN10-MODETAB ;14 DC.W XMAIN11-MODETAB ;16 DC.W cMain0-ModeTab ;18 src --> dst (fg ≠ black or bg ≠ white) DC.W cMain1-ModeTab ;1A src OR dst (fg ≠ black) DC.W Hilite-ModeTab ;1C DST fg <--> bg DC.W cMain3-ModeTab ;1E src BIC dst (bg ≠ white) DC.W END0-MODETAB ;20 JUMP TABLE USED IF DST FITS IN ONE LONG WIDE DC.W END1-MODETAB ;22 DC.W END2-MODETAB ;24 DC.W END3-MODETAB ;26 DC.W LONG8-MODETAB ;28 DC.W END9-MODETAB ;2A DC.W END10-MODETAB ;2C DC.W END11-MODETAB ;2E DC.W XLONG8-MODETAB ;30 EXPANDED PATTERN MODES DC.W XEND9-MODETAB ;32 DC.W XEND10-MODETAB ;34 DC.W XEND11-MODETAB ;36 DC.W cEnd0-ModeTab ;38 src --> dst (fg ≠ black or bg ≠ white) DC.W cEnd1-ModeTab ;3A src OR dst (fg ≠ black) DC.W SloHilite-ModeTab ;3C (src, pat is mask) DST fg <--> bg DC.W cEnd3-ModeTab ;3E src BIC dst (bg ≠ white) DC.W Avg-ModeTab ;40 AVG(SRC, DST, WEIGHT) --> DST DC.W AddPin-ModeTab ;42 SRC + DST --> DST (pin to max) DC.W AddOver-ModeTab ;44 SRC + DST --> DST (no pin) DC.W SubPin-ModeTab ;46 DST - SRC --> DST (pin to min) DC.W Transparent-ModeTab ;48 SRC less bg --> DST DC.W Max-ModeTab ;4A MAX(SRC, DST) --> DST DC.W SubOver-ModeTab ;4C DST - SRC --> DST (no pin) DC.W Min-ModeTab ;4E MIN(SRC, DST) --> DST ENDIF ALIGN 4 if Quicker then IMPORT bAddOver8 IMPORT bSubOver8 IMPORT bAddPin8 IMPORT bSubPin8 IMPORT bMax8 IMPORT bMin8 IMPORT bAvg8,bTransparent8 bArith8Tab DC.L bAvg8-bArith8Tab ;18 AVG(SRC, DST, WEIGHT) --> DST DC.L bAddPin8-bArith8Tab ;1A SRC + DST --> DST (pin to max) DC.L bAddOver8-bArith8Tab ;1C SRC + DST --> DST (no pin) DC.L bSubPin8-bArith8Tab ;1E DST - SRC --> DST (pin to min) DC.L bTransparent8-bArith8Tab ;20 SRC less bg --> DST DC.L bMax8-bArith8Tab ;22 MAX(SRC, DST) --> DST DC.L bSubOver8-bArith8Tab ;24 DST - SRC --> DST (no pin) DC.L bMin8-bArith8Tab ;26 MIN(SRC, DST) --> DST DC.L bAvg8-bArith8Tab ;50% case endif if blit32 then ;<14> bArith16Tab DC.L bAvg16-bArith16Tab ;18 AVG(SRC, DST, WEIGHT) --> DST DC.L bAddPin16-bArith16Tab ;1A SRC + DST --> DST (pin to max) DC.L bAddOver16-bArith16Tab ;1C SRC + DST --> DST (no pin) DC.L bSubPin16-bArith16Tab ;1E DST - SRC --> DST (pin to min) DC.L bTransparent16-bArith16Tab ;20 SRC less bg --> DST DC.L bMax16-bArith16Tab ;22 MAX(SRC, DST) --> DST DC.L bSubOver16-bArith16Tab ;24 DST - SRC --> DST (no pin) DC.L bMin16-bArith16Tab ;26 MIN(SRC, DST) --> DST DC.L bAvg16Half-bArith16Tab ;50% case bArith32Tab DC.L bAvg32-bArith32Tab ;18 AVG(SRC, DST, WEIGHT) --> DST DC.L bAddPin32-bArith32Tab ;1A SRC + DST --> DST (pin to max) DC.L bAddOver32-bArith32Tab ;1C SRC + DST --> DST (no pin) DC.L bSubPin32-bArith32Tab ;1E DST - SRC --> DST (pin to min) DC.L bTransparent32-bArith32Tab ;20 SRC less bg --> DST DC.L bMax32-bArith32Tab ;22 MAX(SRC, DST) --> DST DC.L bSubOver32-bArith32Tab ;24 DST - SRC --> DST (no pin) DC.L bMin32-bArith32Tab ;26 MIN(SRC, DST) --> DST DC.L bAvg32Half-bArith32Tab ;50% case else ;<14> bArith16Tab bArith32Tab endif ;<14> bHiliteTab ; (1-bit hilite converted to Xor) DC.L bHilite-bHiliteTab ; 2-bit DC.L bHilite-bHiliteTab ; 4-bit DC.L bHilite-bHiliteTab ; 8-bit if blit32 then ;<14> DC.L bHilite-bHiliteTab ;16-bit DC.L bHilite32-bHiliteTab ;32-bit endif ;<14> ALIGN Alignment ;------------------------------------------------------------ ; ; OPTIMIZE RIGHT HORIZONTAL SCROLL IF NO SHIFT. ; ONLY IF MODE 0, BUMPING RIGHT TO LEFT, LONGCNT > 0, AND NO SHIFT. ; bLEFT0 MOVE.L D4,D1 ;MASK:=FIRSTMASK MOVE LONGCNT(A6),D2 ;GET LONGCOUNT MOVE.L (A4),D0 ;GET SRC FROM BITMAP ADD A0,A4 ;BUMP LEFT AND.L D1,D0 ;MASK FIRST LONG NOT.L D1 ;MAKE NOTMASK AND.L (A5),D1 ;GET DATA FROM DST OR.L D1,D0 ;MERGE WITH SRC DATA MOVE.L D0,(A5) ;PUT RESULT TO DST ADD A0,A5 ;BUMP LEFT SUB #1,D2 ;DEC LONG COUNT BEQ.S LLast0 ;BR IF NO UNMASKED LONGS SUB A0,A4 ;GET READY FOR PRE-DECREMENT SUB A0,A5 ;GET READY FOR PRE-DECREMENT BRA.S LONE0 ;GO MOVE A LONG LTWO0 MOVE.L -(A4),-(A5) ;MOVE A LONG LONG LONE0 MOVE.L -(A4),-(A5) ;MOVE ANOTHER LONG SUB #2,D2 ;ANY UNMASKED LONGS LEFT IN ROW ? BGT LTWO0 ;YES, AT LEAST 2 LONGS LEFT BEQ LONE0 ;YES, FINISH UP LAST LONG ADD A0,A4 ;RETURN TO NORMAL AFTER PRE-DECREMENT ADD A0,A5 ;RETURN TO NORMAL AFTER PRE-DECREMENT LLast0 MOVE.L D5,D1 ;copy last mask MOVE.L (A4),D0 ;get last long of src from bitmap ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT AND.L D1,D0 ;MASK SRC NOT.L D1 ;FORM NOTMASK AND.L (A5),D1 ;GET DST DATA OR.L D1,D0 ;MERGE WITH SRC DATA MOVE.L D0,(A5) ;PUT RESULT TO DST ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT ADD SRCBUMP(A6),A4 ;BUMP SRCPTR TO NEXT ROW ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT BNE.S bLEFT0 ;LOOP FOR ALL SRCROWS BRA.S GOHOME ;THEN QUIT ;------------------------------------------------------------ ; ; <14> All new fast scrolling routine that takes advantage of the ; MOVE16 instruction on the 68040 when possible. ; ;------------------------------------------------------- ; a0 = JUMPA d0 = SCRATCH ; a1 = JUMPB d1 = ,SCRATCH ; a2 = JUMPC d2 = LEFTLONGS,SCRATCH ; a3 = JUMPD d3 = RIGHTLONGS,QUADBLOCKS ; a4 = d4 = ; a5 = d5 = ; a6 = locals d6 = SRCWID ; a7 = sp d7 = DSTWID ;------------------------------------------------------- bSETUP0 OFFSET EQU 38 MOVE SRCBUMP(A6),D6 ;get srcwid into a register MOVE A3,D7 ;put dstwid into a more useful register MOVEQ #$F,D1 ;get useful mask ADDQ #1,D2 ;make longs width one based CMP.B #cpu68040,cpuFlag ;is this an '040 or greater machine? BLT.S @normal ;no, use normal case CMP #8,D2 ;are at least 8 longs being moved? BLT.S @normal ;no, use normal case ; <02OCT92 SAH> <24> ; we need to make sure that everything is long aligned. If srcPtr, dstPtr, srcWid or dstWid ; are word aligned, we need to go slow... move.w a4,d0 ;get copy of src address <02OCT92 SAH> <24> move.w a5,d3 ;get copy of dst address <02OCT92 SAH> <24> or.w d3,d0 ;or in with src address <02OCT92 SAH> <24> or.w d6,d0 ;or in srcWid <02OCT92 SAH> <24> or.w d7,d0 ;or in dstWid <02OCT92 SAH> <24> and.w #3,d0 ;and all four with long align mask <02OCT92 SAH> <24> bne.s @normal ;if any one is word aligned, go slow <02OCT92 SAH> <24> MOVE D2,D3 ;are srcwid and dstwid both quadlong multiples? LSL #2,D3 ; ((srcwid + (longs*4)) | (dstwid + (longs*4))) & 0x000F == 0) MOVE D6,D0 ADD D3,D0 ADD D7,D3 OR D0,D3 AND D1,D3 BNE.S @normal ;no, use normal case MOVE.L A4,D3 ;do srcptr and dstptr have same quadlong phase? SUB.L A5,D3 ; (srcptr - dstptr) & 0x000F == 0) AND D1,D3 BEQ.S @fast ;yes, use fast case @normal MOVE D2,D3 ;count = longs MOVEQ #0,D0 ADDQ.L #1,D4 ;count += (leftmask++ == -1) ADDX D0,D3 ADDQ.L #1,D5 ;count += (rightmask++ == -1) ADDX D0,D3 MOVE.L D5,D0 ;JUMPD = &@right + (rightmask ? (@right - @rmask) : 0) BEQ.S @0 MOVEQ #-OFFSET,D0 @0: LEA (@right,D0.W),A3 MOVE.L A3,A1 ;JUMPB = JUMPD SUBQ #3,D3 ;if ((count -= 3) < 0) BMI.S @5 ; goto @5 AND D3,D1 ;JUMPB = &@mv4 - (count % 16) * 2 NEG D1 LEA (@mv4,D1.W*2),A1 LSR #4,D3 ;count /= 16; BRA.S @5 @fast MOVEQ #-1,D0 MOVE.W A4,D3 ;leftlongs = (-srcptr % 16) / 4 NEG D3 AND.W D3,D1 LSR.W #2,D1 SUB D1,D2 ;longs -= leftlongs ADDQ.L #1,D4 ;leftlongs -= (leftmask++ != -1) ADDX D0,D1 BGE.S @1 ;if (leftlongs < 0) MOVEQ #3,D1 ; leftlongs = 3 SUBQ #4,D2 ; longs -= 4 @1: MOVEQ #3,D3 ;rightlongs = longs & 0x03 AND D2,D3 SUB D3,D2 ;longs -= rightlongs ADDQ.L #1,D5 ;rightlongs -= (rightmask++ != -1) ADDX D0,D3 BGE.S @2 ;if (rightlongs < 0) MOVEQ #3,D3 ; rightlongs = 3 SUBQ #4,D2 ; longs -= 4 @2: NEG D3 ;JUMPD = &@right + (-rightlongs * 2) LEA (@right,D3.W*2),A3 TST.L D5 ;if (rightmask - 1 != -1) BEQ.S @3 SUB #OFFSET,A3 ; JUMPD -= @right - @rmask; @3: MOVE.L A3,A2 ;JUMPC = JUMPD LSR #2,D2 ;longs /= 4 BEQ.S @4 ;if (longs) SUBQ #1,D2 ; longs-- MOVE D2,D3 ; quadblocks = longs / 8 LSR #3,D3 AND #$07,D2 ; JUMPC = &@mv16 + (-(longs & 0x7) * 4) NEG D2 LEA (@mv16,D2.W*4),A2 @4: MOVE.L A2,A1 ;JUMPB = JUMPC MOVE D1,D2 ;if (leftlongs != 0) BEQ.S @5 NEG D2 ; JUMPB = &@left - (leftlongs * 2) LEA (@left,D2.W*2),A1 @5: MOVE.L A1,A0 ;JUMPA = JUMPB TST.L D4 ;if (leftmask - 1 != -1) BEQ.S @6 LEA @lmask,A0 ; JUMPA = &@lmask @6: SUBQ.L #1,D4 ;++leftmask SUBQ.L #1,D5 ;++rightmask MOVE.L HEIGHT(A6),D1 ;(put height into high word) MOVE D3,D1 ;(set up initial quadblocks count) nop ;finish any write in pipeline (may not need this one) JMP (A0) MACRO ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 myMOVE16 ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 DC.L $F624D000 ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 ENDM ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 ALIGN Alignment @lmask MOVE.L (A4)+,D0 ;get long of src MOVE.L (A5),D2 ;get long of dst EOR.L D2,D0 ; AND.L D4,D0 ;splice src and dst together through leftmask EOR.L D2,D0 ; MOVE.L D0,(A5)+ ;save result to dst nop ;finish any write in pipeline JMP (A1) ;go copy partial or full quadlong blocks MOVE.L (A4)+,(A5)+ ;copy partial left quadlong block MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ @left nop ;finish any write in pipeline JMP (A2) ;go copy quadlong blocks @mv256 myMOVE16 ;MOVE16 (A4)+,(A5)+ ;copy 32 longs myMOVE16 ;MOVE16 (A4)+,(A5)+ myMOVE16 ;MOVE16 (A4)+,(A5)+ myMOVE16 ;MOVE16 (A4)+,(A5)+ myMOVE16 ;MOVE16 (A4)+,(A5)+ ;copy 16 longs myMOVE16 ;MOVE16 (A4)+,(A5)+ myMOVE16 ;MOVE16 (A4)+,(A5)+ @mv16 myMOVE16 ;MOVE16 (A4)+,(A5)+ ;copy 4 longs DBRA D1,@mv256 ;dec counter and go do another 32 longs JMP (A3) ;go finish right edge of scanline @mv64 MOVE.L (A4)+,(A5)+ ;copy 16 longs MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ ;copy 8 longs MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ @mv4 MOVE.L (A4)+,(A5)+ ;copy 1 long DBRA D1,@mv64 ;dec count and go do another 16 longs JMP (A3) ;go finish right edge of scanline MOVE.L (A4)+,(A5)+ ;copy partial right quadlong block MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ @rmask MOVE.L (A4)+,D0 ;get long of src MOVE.L (A5),D2 ;get long of dst EOR.L D2,D0 AND.L D5,D0 ;splice src and dst together through rightmask EOR.L D2,D0 MOVE.L D0,(A5)+ ;save result to dst ADD D6,A4 ;bump srcptr by (srcbump - (longcnt * 4)) ADD D7,A5 ;bump dstptr by (dstbump - (longcnt * 4)) MOVE D3,D1 ;restore quadblock count SWAP D1 ;swap linecount into low word SUBQ #1,D1 ;decrement linecount BEQ GoHome ;leave if zero SWAP D1 ;swap linecount out of low word nop ;finish any write in pipeline JMP (A0) ;go do another line MOVE.L (A4)+,(A5)+ ;copy partial right quadlong block MOVE.L (A4)+,(A5)+ MOVE.L (A4)+,(A5)+ @right ADD D6,A4 ;bump srcptr by (srcbump - (longcnt * 4)) ADD D7,A5 ;bump dstptr by (dstbump - (longcnt * 4)) MOVE D3,D1 ;restore quadblock count SWAP D1 ;swap linecount into low word SUBQ #1,D1 ;decrement linecount BEQ.S GoHome ;leave if zero SWAP D1 ;swap linecount out of low word nop ;finish any write in pipeline JMP (A0) ;go do another line IF @right - @rmask - OFFSET THEN AERROR '••• Offset assumption is bad •••' ENDIF ALIGN Alignment ;------------------------------------------------------- ; ; MODE 0 or 4: SRC --> DST ; ; <20Jul90 SMC> ; Split loop into shift and no shift cases, and separated ; out the blitting of the longs between the left and right ; masks in both cases. ; bEND0 AND.L D5,D1 ;firstmask = firstmask AND lastmask MOVE.L D1,FIRSTMASK(A6) ;make it stick for remaining scan lines bMAIN0 LEA bMAIN0A,A1 ;get address of no shift case TST.L D6 ;check if shift = 0 BNE.S @1 ;if not, go blit LEA bMAIN0B,A1 ;if shift != 0, use shift case @1: JMP (A1) ;jump to blit loop ; ; Shifted srcCopy/notSrcCopy case ; bEND0A MOVE.L D5,D1 ;mask = lastmask bMAIN0A BFEXTU (A4){D6:0},D0 ;get long of src from bitmap ADD A0,A4 ;bump srcptr left or right EOR.L D7,D0 ;invert src if mode bit 2 set AND.L D1,D0 ;mask src NOT.L D1 ;form notmask AND.L (A5),D1 ;get dest data OR.L D1,D0 ;splice with src data MOVE.L D0,(A5) ;put result into dst ADD A0,A5 ;bump dstptr left or right SUB #1,D2 ;dec long count BEQ bEND0A ;do last long with lastmask BLT NXTSRC ;loop back for next scan line bMID0A BFEXTU (A4){D6:0},D0 ;get long of src from bitmap ADD A0,A4 ;bump srcptr left or right EOR.L D7,D0 ;invert src if mode bit 2 set MOVE.L D0,(A5) ;put result into dest ADD A0,A5 ;bump dstptr left or right SUB #1,D2 ;dec long count BGT bMID0A ;branch if unmasked longs left BRA bEND0A ;do last long with lastmask ; ; No shift srcCopy/notSrcCopy case ; bEND0B MOVE.L D5,D1 ;mask = lastmask bMAIN0B MOVE.L (A4),D0 ;get long of src from bitmap ADD A0,A4 ;bump srcptr left or right EOR.L D7,D0 ;invert src if mode bit 2 set AND.L D1,D0 ;mask src NOT.L D1 ;form notmask AND.L (A5),D1 ;get dst data OR.L D1,D0 ;merge with src data MOVE.L D0,(A5) ;put result to dst ADD A0,A5 ;bump dstptr left or right SUB #1,D2 ;dec long count BEQ bEND0B ;do last long with lastmask BLT NXTSRC ;loop back for next scan line bMID0B MOVE.L (A4),D0 ;get long of src from bitmap ADD A0,A4 ;bump srcptr left or right EOR.L D7,D0 ;invert src if mode bit 2 set MOVE.L D0,(A5) ;put result into dest ADD A0,A5 ;bump dstptr left or right SUB #1,D2 ;dec long count BGT bMID0B ;branch if unmasked longs left BRA bEND0B ;do last long with lastmask ALIGN Alignment ;------------------------------------------------------- ; ; MODE 1 or 5: SRC OR DST --> DST ; ; <20Jul90 SMC> ; Split loop into shift and no shift cases. ; bEND1 AND.L D5,D1 ;firstmask = firstmask AND lastmask MOVE.L D1,FIRSTMASK(A6) ;make it stick for remaining scan lines bMAIN1 LEA bMAIN1A,A1 ;get address of no shift case TST.L D6 ;check if shift = 0 BNE.S @1 ;if not, go blit LEA bMAIN1B,A1 ;if shift != 0, use shift case @1: JMP (A1) ;jump to blit loop ; ; Shifted srcOr/notSrcOr case ; bEND1A MOVE.L D5,D1 ;mask = lastmask bMAIN1A BFEXTU (A4){D6:0},D0 ;get src from bitmap with shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D1,D0 ;MASK SRC OR.L D0,(A5) ;OR SRC INTO DST ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN1A ;LOOP TILL LAST LONG BEQ bEND1A ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ; ; No shift srcOr/notSrcOr case ; bEND1B MOVE.L D5,D1 ;mask = lastmask bMAIN1B MOVE.L (A4),D0 ;get src from bitmap without shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D1,D0 ;MASK SRC OR.L D0,(A5) ;OR SRC INTO DST ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN1B ;LOOP TILL LAST LONG BEQ bEND1B ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;------------------------------------------------------- ; ; MODE 2 or 6: SRC XOR DST --> DST ; ; <20Jul90 SMC> ; Split loop into shift and no shift cases. ; bEND2 AND.L D5,D1 ;firstmask = firstmask AND lastmask MOVE.L D1,FIRSTMASK(A6) ;make it stick for remaining scan lines bMAIN2 LEA bMAIN2A,A1 ;get address of no shift case TST.L D6 ;check if shift = 0 BNE.S @1 ;if not, go blit LEA bMAIN2B,A1 ;if shift != 0, use shift case @1: JMP (A1) ;jump to blit loop ; ; Shifted srcXor/notSrcXor case ; bEND2A MOVE.L D5,D1 ;mask = lastmask bMAIN2A BFEXTU (A4){D6:0},D0 ;get src from bitmap with shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D1,D0 ;MASK SRC EOR.L D0,(A5) ;XOR SRC INTO DST ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN2A ;LOOP TILL LAST LONG BEQ bEND2A ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ; ; No shift srcXor/notSrcXor case ; bEND2B MOVE.L D5,D1 ;mask = lastmask bMAIN2B MOVE.L (A4),D0 ;get src from bitmap without shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D1,D0 ;MASK SRC EOR.L D0,(A5) ;XOR SRC INTO DST ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN2B ;LOOP TILL LAST LONG BEQ bEND2B ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;------------------------------------------------------- ; ; MODE 3 or 7: SRC BIC DST --> DST ; ; <20Jul90 SMC> ; Split loop into shift and no shift cases. ; bEND3 AND.L D5,D1 ;firstmask = firstmask AND lastmask MOVE.L D1,FIRSTMASK(A6) ;make it stick for remaining scan lines bMAIN3 LEA bMAIN3A,A1 ;get address of no shift case TST.L D6 ;check if shift = 0 BNE.S @1 ;if not, go blit LEA bMAIN3B,A1 ;if shift != 0, use shift case @1: JMP (A1) ;jump to blit loop ; ; Shifted srcBic/notSrcBic case ; bEND3A MOVE.L D5,D1 ;mask = lastmask bMAIN3A BFEXTU (A4){D6:0},D0 ;get src from bitmap with shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D1,D0 ;MASK SRC NOT.L D0 ;INVERT SRC AND.L D0,(A5) ;BIT CLEAR SRC INTO DST ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN3A ;LOOP TILL LAST LONG BEQ bEND3A ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ; ; No shift srcBic/notSrcBic case ; bEND3B MOVE.L D5,D1 ;mask = lastmask bMAIN3B MOVE.L (A4),D0 ;get src from bitmap without shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D1,D0 ;MASK SRC NOT.L D0 ;INVERT SRC AND.L D0,(A5) ;BIT CLEAR SRC INTO DST ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN3B ;LOOP TILL LAST LONG BEQ bEND3B ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;------------------------------------------------------- ; ; MODE 0 or 4: SRC --> DST (foreground ≠ black or background ≠ white) ; ; <20Jul90 SMC> ; Split loop into three cases. Shifted and colorized srcCopy, ; shifted and colorized notSrcCopy, and not shifted but colorized ; srcCopy/notSrcCopy. In all three cases, the blitting of the longs ; between the left and right masks done separately for speed. ; ; The shifted, colorized srcCopy and notSrcCopy cases were split so ; that the notmask register was free to speed up colorizing. The ; old loop used the stack which cost two reads and two writes. ; bcEND0 AND.L D5,D1 ;firstmask = firstmask AND lastmask MOVE.L D1,FIRSTMASK(A6) ;make it stick for remaining scan lines bcMAIN0 EOR.L D4,D3 ;munge FG and BK colors once for rest of scan lines LEA bcMAIN0C,A1 ;get address of no shift case TST.L D6 ;check if shift = 0 BEQ.S @1 ;is so, go blit LEA bcMAIN0B,A1 ;get address of shifted notSrcCopy case TST.L D7 ;is this the not mask true? BNE.S @1 ;yes, go blit LEA bcMAIN0A,A1 ;get address of shifted srcCopy case @1: JMP (A1) ;go blitting ; ; Shifted and colorized srcCopy case ; bcEND0A MOVE.L D5,D1 ;mask = lastmask bcMAIN0A BFEXTU (A4){D6:0},D0 ;get long of src from bitmap with shift ADD A0,A4 ;bump srcptr left or right AND.L D3,D0 ;apply FG color to ones of src EOR.L D4,D0 ;apply BK color to zeroes of src MOVE.L (A5),D7 ;get long from dest EOR.L D7,D0 ;splice colorized src into dst AND.L D1,D0 ; using first or last mask EOR.L D7,D0 MOVE.L D0,(A5) ;move result to dst ADD A0,A5 ;bump dstptr left or right SUB #1,D2 ;dec long count BEQ bcEND0A ;DO LAST LONG WITH LASTMASK BLT NXTSRC ;LOOP BACK FOR MORE bcMID0A BFEXTU (A4){D6:0},D0 ;get long of src from bitmap with shift ADD A0,A4 ;bump srcptr left or right AND.L D3,D0 ;apply FG color to ones of src EOR.L D4,D0 ;apply BK color to zeroes of src MOVE.L D0,(A5) ;move result to dst ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT SUB #1,D2 ;DEC LONG COUNT BGT bcMID0A ;BR IF UNMASKED LONGS LEFT BRA bcEND0A ;DO LAST LONG WITH LASTMASK ; ; Shifted and colorized notSrcCopy case ; bcEND0B MOVE.L D5,D1 ;mask = lastmask bcMAIN0B BFEXTU (A4){D6:0},D0 ;get long of src from bitmap with shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT NOT.L D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D3,D0 ;apply FG color to ones of src EOR.L D4,D0 ;apply BK color to zeroes of src MOVE.L (A5),D7 ;get long from dest EOR.L D7,D0 ;splice colorized src into dst AND.L D1,D0 ; using first or last mask EOR.L D7,D0 MOVE.L D0,(A5) ;move result to dst ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT SUB #1,D2 ;DEC LONG COUNT BEQ bcEND0B ;DO LAST LONG WITH LASTMASK BLT NXTSRC ;LOOP BACK FOR MORE bcMID0B BFEXTU (A4){D6:0},D0 ;get long of src from bitmap with shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT NOT.L D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D3,D0 ;apply FG color to ones of src EOR.L D4,D0 ;apply BK color to zeroes of src MOVE.L D0,(A5) ;move result to dst ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT SUB #1,D2 ;DEC LONG COUNT BGT bcMID0B ;BR IF UNMASKED LONGS LEFT BRA bcEND0B ;DO LAST LONG WITH LASTMASK ; ; No shift but colorized srcCopy/notSrcCopy case ; bcEND0C MOVE.L D5,D1 ;mask = lastmask bcMAIN0C MOVE.L (A4),D0 ;get long of src from bitmap without shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D3,D0 ;apply FG color to ones of src EOR.L D4,D0 ;apply BK color to zeroes of src MOVE.L (A5),D6 ;get long from dest EOR.L D6,D0 ;splice colorized src into dst AND.L D1,D0 ; using first or last mask EOR.L D6,D0 MOVE.L D0,(A5) ;move result to dst ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT SUB #1,D2 ;DEC LONG COUNT BEQ bcEND0C ;DO LAST LONG WITH LASTMASK BLT NXTSRC ;LOOP BACK FOR MORE bcMID0C MOVE.L (A4),D0 ;get long of src from bitmap without shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L D3,D0 ;apply FG color to ones of src EOR.L D4,D0 ;apply BK color to zeroes of src MOVE.L D0,(A5) ;move result to dst ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT SUB #1,D2 ;DEC LONG COUNT BGT bcMID0C ;BR IF UNMASKED LONGS LEFT BRA bcEND0C ;DO LAST LONG WITH LASTMASK ALIGN Alignment ;------------------------------------------------------- ; ; MODE 1 or 5: SRC OR DST --> DST (foreground ≠ black) ; MODE 3 or 7: SRC BIC DST --> DST (background ≠ white) ; ; <20Jul90 SMC>, <18Oct90 SMC> <12> ; Folded BIC loop into OR loop by making forecolor equal backcolor. ; Split OR loop into two cases. Shifted and colorized srcOr/notSrcOr, and ; colorized, not shifted srcOr/notSrcOr. In both cases, the blitting of ; the longs between the left and right masks are done separately for speed. ; bcEND3 MOVE.L D4,D3 bcEND1 AND.L D5,D1 ;firstmask = firstmask AND lastmask MOVE.L D1,FIRSTMASK(A6) ;make it stick for remaining scan lines BRA.S bcMAIN1 bcMAIN3 MOVE.L D4,D3 bcMAIN1 LEA bcMAIN1B,A1 ;get address of no shift case TST.L D6 ;check if shift = 0 BEQ.S bcMAIN1B ;is so, go blit LEA bcMAIN1A,A1 ;get address of shift case JMP (A1) ;go blitting ; ; Colorized, shifted srcOr/notSrcOr case ; bcEND1A MOVE.L D5,D1 ;mask = lastmask bcMAIN1A BFEXTU (A4){D6:0},D0 ;get src from bitmap with shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET MOVE.L (A5),D4 ;get long of dst AND.L D1,D0 ;combine src and left or right mask NOT.L D0 ;reverse the mask EOR.L D3,D4 ;splice colorized src into dst AND.L D0,D4 ; using mask EOR.L D3,D4 MOVE.L D4,(A5) ;move result to dst ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bcMAIN1A ;LOOP TILL LAST LONG BEQ bcEND1A ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ; ; Colorized, not shifted srcOr/notSrcOr case ; bcEND1B MOVE.L D5,D1 ;mask = lastmask bcMAIN1B MOVE.L (A4),D0 ;get src from bitmap without shift ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET MOVE.L (A5),D4 ;get long of dst AND.L D1,D0 ;combine src and left or right mask NOT.L D0 ;reverse the mask EOR.L D3,D4 ;splice colorized src into dst AND.L D0,D4 ; using mask EOR.L D3,D4 MOVE.L D4,(A5) ;move result to dst ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bcMAIN1B ;LOOP TILL LAST LONG BEQ bcEND1B ;DO LAST LONG WITH LASTMASK BRA NXTSRC ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;----------------------------------------------------------- ; ; OPTIMIZE MODE 8 OR 12 IF DST FITS IN ONE LONG (VERT LINES ETC) ; ; <13> fix as seen in QDciPatchROM.a stb bLONG8 AND.L alphaMask(A6),D1 ;clip left mask with alpha mask <13> MOVE HEIGHT(A6),D3 ;GET NUMBER OF ROWS move.l exPat(a6),a4 ;get pattern pointer <1.5> BAL lea (a4,d7*4),a2 ;point into pattern <1.5> BAL addq #4,a3 ;convert dstBump to rowBytes <1.5> BAL SUBQ #1,D3 ;MAKE 0 BASED FOR DBRA LOOP AND.L D5,D1 ;COMBINE LEFT AND RIGHT MASKS MOVE.L D1,D5 ;COPY COMBINED MASK MOVE.L A4,A1 ;pointer to first long <1.5> BAL MOVE.L (A1)+,D0 ;get first long of pattern <1.5> BAL MOVEQ #$0E,D2 ;15-1 longs remaining <1.5> BAL @nextLong CMP.L (A1)+,D0 ;is it solid? <1.5> BAL DBNE D2,@nextLong ;check all of the pattern for equality BEQ.S SolidVert ;if all same, do fast way <1.5> BAL NOT.L D5 ;FORM NOTMASK beq.s Long32 ;no need to mask <1.5> BAL LONG8 AND.L D1,D6 ;MASK EXTRA PATTERN TO ZEROS MOVE.L (A5),D0 ;GET DST DATA AND.L D5,D0 ;AND WITH NOTMASK OR.L D6,D0 ;MERGE WITH SRC DATA MOVE.L D0,(A5) ;PUT RESULT TO DST ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW ADD #1,D7 ;BUMP PATTERN SELECTOR AND #$0F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L (a4,D7*4),D6 ;GET PATTERN DATA <1.5> BAL DBRA D3,LONG8 ;LOOP ALL ROWS BRA GOHOME LONG32 MOVE.L (a2)+,(A5) ;PUT pattern TO DST <1.5> BAL ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW <1.5> BAL ADD #1,D7 ;BUMP PATTERN SELECTOR <1.5> BAL AND #$0F,D7 ;MOD 16 FOR 16 LONG REPEAT <1.5> BAL bne.s @patOK ; <1.5> BAL MOVE.L a4,a2 ;reload pattern pointer <1.5> BAL @patOK DBRA D3,LONG32 ;LOOP ALL ROWS <1.5> BAL BRA GOHOME ; <1.5> BAL ALIGN Alignment ;----------------------------------------------------------- ; ; OPTIMIZE MODE 8 OR 12 IF DST FITS IN ONE LONG AND SOLID PATTERN ; ; Enter with pattern in D0 ; SolidVert NOT.L D5 ;FORM NOTMASK <1.5> BAL beq.s @Long32 ;no need to mask <1.5> BAL AND.L D1,D0 ;MASK EXTRA PATTERN TO ZEROS <1.5> BAL @LONG8 MOVE.L (A5),D2 ;GET DST DATA <1.5> BAL AND.L D5,D2 ;AND WITH NOTMASK <1.5> BAL OR.L D0,D2 ;MERGE WITH SRC DATA <1.5> BAL MOVE.L D2,(A5) ;PUT RESULT TO DST <1.5> BAL ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW <1.5> BAL DBRA D3,@LONG8 ;LOOP ALL ROWS <1.5> BAL BRA GOHOME ; <1.5> BAL @LONG32 MOVE.L D0,(A5) ;PUT pattern TO DST <1.5> BAL ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW <1.5> BAL DBRA D3,@LONG32 ;LOOP ALL ROWS <1.5> BAL BRA GOHOME ; <1.5> BAL ALIGN Alignment ;------------------------------------------------------------ ; ; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES) ; ;------------------------------------------------------- ; a0 = moveTablePtr d0 = scratch ; a1 = ~firstMask d1 = scratch ; a2 = ~lastMask d2 = rowCount ; a3 = hBump d3 = blockCount ; a4 = patterPtr d4 = firstMask ; a5 = dstPtr d5 = lastMask ; a6 = locals d6 = pattern data ; a7 = sp d7 = pattern selector ;------------------------------------------------------- ; <13> Start of alpha channel changes as seen in QDciPatchROM.a stb bSETUP8 TST.B alphaMode(A6) ;drawing in alpha mode? BEQ.S @bSETUP8 ;no, use normal loop MOVE.L alphaMask(A6),D3 ;get alpha mask AND.L D3,D1 ;AND ALPHA WITH LEFT MASK MOVE.L D1,FIRSTMASK(A6) ;SAVE THAT RESULT AND.L D3,D5 ;AND ALPHA WITH RIGHT MASK BRA.S @bMAIN8 ;jump into alpha loop @bEND8 AND.L D5,D1 ;MASK:=MASK AND LASTMASK @bMAIN8 MOVE.L D1,D0 ;COPY MASK AND.L D6,D1 ;GET MASKED PATTERN NOT.L D0 ;REVERSE MASK AND.L (A5),D0 ;GET NOT MASKED DST OR.L D1,D0 ;COMBINE PATTERN AND DST MOVE.L D0,(A5)+ ;PUT RESULT TO DST MOVE.L D3,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT @bMAIN8 ;LOOP TILL LAST LONG BEQ @bEND8 ;DO LAST LONG WITH LASTMASK @NXTPAT ADD #1,D7 ;BUMP PATTERN SELECTOR AND #$0F,D7 ;MOD 16 FOR 16 LONG REPEAT MOVE.L ([EXPAT,A6],D7*4),D6 ;GET FIRST PATTERN DATA ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT BEQ.S GOHOME ;LOOP FOR ALL SRCROWS MOVE.L FIRSTMASK(A6),D1 ;MASK:=FIRSTMASK MOVE LONGCNT(A6),D2 ;GET LONGCOUNT BRA.S @bMAIN8 ;GO NEXT LINE ; <13> End of alpha channel changes @bSETUP8 ; ; <02OCT92 SAH> <24> ; We first need to check if we can go fast. There are several conditions for this: ; 1. At least 16 longs are being moved (otherwise slow case is faster) ; 2. The destination address is long aligned (we cannot handle word aligned addresses). ; 3. hBump is a long multiple (same reason as 3). ; 4. The dst maintains the same quadlong phase across all scanlines ; 5. The pattern is constant. ; cmp.w #16,d2 ; must have at least 16 to make fast case worthwhile (cond 1) blt.s @slowCase ; less, so go slow cmp.b #cpu68040,cpuFlag ;is this an '040 or greater machine? blt.s @slowCase ; less, so go slow move.w a5,d0 ; get copy of dst address (cond 2 and 3) <02OCT92 SAH> <24> move.w a3,d3 ; get copy of hBump <02OCT92 SAH> <24> or.w d3,d0 ; or it in <02OCT92 SAH> <24> and.w #3,d0 ; check if hBump and dst address are long aligned <02OCT92 SAH> <24> bne.s @slowCase ; either one is word aligned, so go slow <02OCT92 SAH> <24> move.w a3,d3 ; get a copy of the hBump (cond 4) <02OCT92 SAH> <24> move.w d2,d0 ; get the number of longs to write <02OCT92 SAH> <24> addq.w #1,d0 ; make it a one based count <02OCT92 SAH> <24> lsl.w #2,d0 ; make it bytes <02OCT92 SAH> <24> add.w d0,d3 ; add the number of bytes to write <02OCT92 SAH> <24> and.w #$f,d3 ; is the quadlong phase the same? <02OCT92 SAH> <24> bne.s @slowCase ; no, so go slow <02OCT92 SAH> <24> move.l expat(a6),a0 ; get start of expanded pattern (cond 5) move.l (a0),d4 ; get first pattern long (d4 not used yet) moveq #15,d0 ; get count @0 cmp.l (a0)+,d4 ; compare dbne d0,@0 ; continue if still equal beq fastBSETUP8 ; if == 0, then pattern is solid and we can go fast @slowCase move.w d2,d3 ; get count of longwords to move move.l d1,d4 ; get copy of firstMask not.l d1 ; invert for dst masking movea.l d1,a1 ; setup inverted firstMask bne.s @hasFirstMask ; if mask is valid, use it addq.w #1,d3 ; if no mask, copy 1 extra long @hasFirstMask move.l d5,d0 ; get copy of lastMask not.l d0 ; invert for dst masking movea.l d0,a2 ; setup inverted lastMask bne.s @hasLastMask ; if mask is valid, use it addq.w #1,d3 ; if no mask, copy 1 extra long @hasLastMask movea.l expat(a6),a4 ; get pointer to base of patterns lea 4(a4,d7.w*4),a4 ; point to next pattern longword move.w d7,d0 ; use pattern index as bit number moveq.l #1,d7 ; use a rotating bit as the pattern counter lsl.w d0,d7 ; position the bit to reflect the pattern index move.w Height(a6),d2 ; get row count subq.w #1,d2 ; zero based for DBRA lea @blockLoopEnd,a0; point to starting address in block move table subq.w #1,d3 ; not counting the last long beq.s @rowStart ; if no longs in the middle, start now moveq.l #$0F,d0 ; mask for initial move count and.w d3,d0 ; get the number of longs to move first neg.w d0 ; index backwards lea -4(a0,d0.w*2),a0; setup the starting address (-4 to bypass DBRA) lsr.w #4,d3 ; setup number of additional blocks of 16 to move bra.s @rowStart ; start now @resetPat moveq.l #1,d7 ; reset the pattern selector suba.w #16*4,a4 ; point back to first pattern @rowLoop move.l (a4)+,d6 ; get source long from pattern @rowStart move.l a1,d1 ; get mask for first long of dest beq.s @no1stMask ; if no masking, just store the source move.l d6,d0 ; get pattern data and.l d4,d0 ; mask first long and.l (a5),d1 ; get first long of dest data or.l d1,d0 ; merge with src data move.l d0,(a5)+ ; put result to dest @no1stMask move.w d3,d0 ; setup block loop counter jmp (a0) ; jump into the move table @blockLoop move.l d6,(a5)+ ; move 16 longs move.l d6,(a5)+ ; move 15 longs move.l d6,(a5)+ ; move 14 longs move.l d6,(a5)+ ; move 13 longs move.l d6,(a5)+ ; move 12 longs move.l d6,(a5)+ ; move 11 longs move.l d6,(a5)+ ; move 10 longs move.l d6,(a5)+ ; move 9 longs move.l d6,(a5)+ ; move 8 longs move.l d6,(a5)+ ; move 7 longs move.l d6,(a5)+ ; move 6 longs move.l d6,(a5)+ ; move 5 longs move.l d6,(a5)+ ; move 4 longs move.l d6,(a5)+ ; move 3 longs move.l d6,(a5)+ ; move 2 longs move.l d6,(a5)+ ; move 1 long dbra d0,@blockLoop ; move remaining blocks of 16 longs @blockLoopEnd move.l a2,d0 ; get mask for last long of dest beq.s @noLstMask ; if no masking, just store the source and.l (a5),d0 ; get last long of dest data and.l d5,d6 ; mask last long or.l d6,d0 ; merge with src data move.l d0,(a5)+ ; put result to dest @noLstMask adda.w a3,a5 ; update dest address add.w d7,d7 ; shift the pattern index dbeq d2,@rowLoop ; loop through all source rows dbne d2,@resetPat ; reset pattern and loop bra.s GoHome ; then quit ; ; <25SEP92 SAH> Fast pattern case for constant patterns. Can only be installed on 040 ; machines when VM is off. ; ;------------------------------------------------------- ; a0 = left block d0 = scratch ; a1 = middle block d1 = scratch ; a2 = right block d2 = scratch ; a3 = middle src d3 = blockCount ; a4 = hBump d4 = firstMask ; a5 = dstPtr d5 = lastMask ; a6 = locals d6 = pattern data ; a7 = sp d7 = stack offset / rowCount ;------------------------------------------------------- ; macro for MOVE16 (A3)+,(A5)+ MACRO ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 aMOVE16 ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 DC.L $F623D000 ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 ENDM ;*** REMOVE WHEN ASSEMBLER KNOWS ABOUT MOVE16 fastBSETUP8 move.w a3,a4 ; put hBump in more consistant register move.w d2,d3 ; get count of longwords to move subq.w #1,d3 ; make one based count of number of middle longs move.l d1,d4 ; get copy of firstMask movea.l expat(a6),a3 ; get ptr to pattern table move.l (a3),d6 ; get source long from pattern ; find offset for left edge alignment moveq #0,d2 ; init left count to zero lea @left,a0 ; get end of left edge table moveq #4,d0 ; figure out the number of left longs 4 - ((a5 + 4) & 0xf) add.w a5,d0 ; (a5 + 4) and.w #$f,d0 ; & 0xf lsr.w #2,d0 ; convert to longs beq.s @leftAligned ; left is already aligned moveq #4,d1 ; sub.w d0,d1 ; 4 - ... sub.w d1,d3 ; subtract the longs we do on the left edge neg.w d1 ; we want to look backwards lea (a0,d1*2),a0 ; get offset @leftAligned ; find offset for right edge alignment lea @right,a2 ; get end of right edge table moveq #3,d2 ; get a mask for right edge count and.w d3,d2 ; get the odd longs neg.w d2 ; offset backwards lea (a2,d2.w*2),a2 ; get start of blit ; now figure out how much to move in the middle lea @blockLoopEnd,a1 ; assume we have nothing to do lsr.w #2,d3 ; each move16 moves 4 longs moveq #$3,d0 ; get mask for first time through (each loop does 4 move16's) and.w d3,d0 ; and find the number to do neg.w d0 ; negate the count lea (a1,d0.w*4),a1 ; offset back into table lsr.w #2,d3 ; convert remaining longs to groups of four ; now create our stack buffer for move16 move.w sp,d0 ; get copy of stack and.w #$f,d0 ; get quadlong mask add.w #64,d0 ; add 64 bytes for base table move.w d0,d7 ; save how much we subtracted... swap d7 ; in high word of d7 sub.w d0,sp ; subtract room on stack moveq #7,d0 ; we want to write 16 longs (we do two at a time) move.l sp,a3 ; get start of table @0 move.l d6,(a3)+ ; fill table move.l d6,(a3)+ ; fill table dbra d0,@0 move.w Height(a6),d7 ; get row count subq.w #1,d7 ; zero based for DBRA @rowLoop move.w d3,d2 ; setup block loop counter (for move16) move.l sp,a3 ; restore block base move.l (a5),d1 ; get a long of dst move.l d6,d0 ; get a long of src eor.l d1,d0 ; and.l d4,d0 ; mask first long eor.l d1,d0 ; move.l d0,(a5)+ ; put result to dest jmp (a0) ; jumpt to start of left edge move.l d6,(a5)+ ; long 1 move.l d6,(a5)+ ; long 2 move.l d6,(a5)+ ; long 3 @left nop ; clear pipeline jmp (a1) ; jump into middle block @blockLoop aMOVE16 ; move16 (a3)+,(a5)+ ; move 16 longs aMOVE16 ; move16 (a3)+,(a5)+ ; move 12 longs aMOVE16 ; move16 (a3)+,(a5)+ ; move 8 longs aMOVE16 ; move16 (a3)+,(a5)+ ; move 4 longs @blockLoopEnd move.l sp,a3 ; restore block base dbra d2,@blockLoop ; move remaining blocks of 16 longs jmp (a2) ; jump into right edge block move.l d6,(a5)+ ; long 1 move.l d6,(a5)+ ; long 2 move.l d6,(a5)+ ; long 3 @right move.l d6,d0 ; get a long of src move.l (a5),d1 ; get a long of dst eor.l d1,d0 ; and.l d5,d0 ; splice with mask eor.l d1,d0 ; move.l d0,(a5)+ ; put result to dest adda.w a4,a5 ; update dest address dbra d7,@rowLoop ; loop through all source rows swap d7 ; get stack offset back add.w d7,sp ; restore stack rts ; then quit ALIGN Alignment ;------------------------------------------------------- ; ; MODE 9 OR 13: PATTERN OR DST --> DST ; bEND9 AND.L D5,D1 ;MASK:=MASK AND LASTMASK bMAIN9 AND.L D6,D1 ;MASK PATTERN MOVE.L D1,D0 ;COPY MASKED PATTERN AND.L D3,D0 ;APPLY FG COLOR TO MASKED PATTERN NOT.L D1 ;GET NOT MASKED PATTERN AND.L (A5),D1 ;USE TO PUNCH OUT DST OR.L D1,D0 ;COMBINE SRC AND DST MOVE.L D0,(A5)+ ;PUT RESULT TO DST MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN9 ;LOOP TILL LAST LONG BEQ bEND9 ;DO LAST LONG WITH LASTMASK BRA NXTPAT ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;----------------------------------------------------------- ; ; OPTIMIZE MODE 10 OR 14 IF DST FITS IN ONE LONG (XOR VERT LINES) ; bEnd10 MOVE HEIGHT(A6),D3 ;GET NUMBER OF ROWS <1.5> BAL move.l exPat(a6),a4 ;get pattern pointer <1.5> BAL lea (a4,d7*4),a2 ;point into pattern <1.5> BAL addq #4,a3 ;convert dstBump to rowBytes <1.5> BAL SUBQ #1,D3 ;MAKE 0 BASED FOR DBRA LOOP <1.5> BAL AND.L D5,D1 ;COMBINE LEFT AND RIGHT MASKS <1.5> BAL @LONG MOVE.L (a2)+,d6 ;get next pattern long <1.5> BAL AND.L D1,D6 ;MASK EXTRA PATTERN TO ZEROS <1.5> BAL EOR.L D6,(A5) ;XOR PATTERN INTO DST <1.5> BAL ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW <1.5> BAL ADD #1,D7 ;BUMP PATTERN SELECTOR <1.5> BAL AND #$0F,D7 ;MOD 16 FOR 16 LONG REPEAT <1.5> BAL bne.s @patOK ; <1.5> BAL MOVE.L a4,a2 ;reload pattern pointer <1.5> BAL @patOK DBRA D3,@LONG ;LOOP ALL ROWS <1.5> BAL BRA GOHOME ; <1.5> BAL ALIGN Alignment ;------------------------------------------------------------ ; ; MODE 10 OR 14: PATTERN XOR DST --> DST (INVERTING AREAS, XOR LINES) ; ;------------------------------------------------------- ; a0 = moveTablePtr d0 = scratch ; a1 = d1 = scratch ; a2 = expat d2 = rowCount ; a3 = hBump d3 = blockCount ; a4 = patterPtr d4 = firstMask ; a5 = dstPtr d5 = lastMask ; a6 = locals d6 = pattern data ; a7 = sp d7 = pattern selector ;------------------------------------------------------- bSETUP10 move.w d2,d3 ; get count of longwords to move move.l d1,d4 ; get copy of firstMask movea.l expat(a6),a2 ; get pointer to base of patterns lea 4(a2,d7.w*4),a4 ; point to next pattern longword move.w d7,d0 ; use pattern index as bit number moveq.l #1,d7 ; use a rotating bit as the pattern counter lsl.w d0,d7 ; position the bit to reflect the pattern index move.w Height(a6),d2 ; get row count subq.w #1,d2 ; zero based for DBRA lea @blockLoopEnd,a0; point to starting address in block move table subq.w #1,d3 ; not counting the last long beq.s @rowStart ; if no longs in the middle, start now moveq.l #$0F,d0 ; mask for initial move count and.w d3,d0 ; get the number of longs to move first neg.w d0 ; index backwards lea -4(a0,d0.w*2),a0; setup the starting address (-4 to bypass DBRA) lsr.w #4,d3 ; setup number of additional blocks of 16 to move bra.s @rowStart ; start now @resetPat moveq.l #1,d7 ; reset the pattern selector movea.l a2,a4 ; point back to first pattern @rowLoop move.l (a4)+,d6 ; get source long from pattern @rowStart move.l d6,d0 ; get pattern data and.l d4,d0 ; mask first long eor.l d0,(a5)+ ; xor pattern into dest move.w d3,d0 ; setup block loop counter jmp (a0) ; jump into the move table @blockLoop eor.l d6,(a5)+ ; move 16 longs eor.l d6,(a5)+ ; move 15 longs eor.l d6,(a5)+ ; move 14 longs eor.l d6,(a5)+ ; move 13 longs eor.l d6,(a5)+ ; move 12 longs eor.l d6,(a5)+ ; move 11 longs eor.l d6,(a5)+ ; move 10 longs eor.l d6,(a5)+ ; move 9 longs eor.l d6,(a5)+ ; move 8 longs eor.l d6,(a5)+ ; move 7 longs eor.l d6,(a5)+ ; move 6 longs eor.l d6,(a5)+ ; move 5 longs eor.l d6,(a5)+ ; move 4 longs eor.l d6,(a5)+ ; move 3 longs eor.l d6,(a5)+ ; move 2 longs eor.l d6,(a5)+ ; move 1 long dbra d0,@blockLoop ; move remaining blocks of 16 longs @blockLoopEnd and.l d5,d6 ; mask last long eor.l d6,(a5)+ ; xor pattern into dest adda.w a3,a5 ; update dest address add.w d7,d7 ; shift the pattern index dbeq d2,@rowLoop ; loop through all source rows dbne d2,@resetPat ; reset pattern and loop bra.s GoHome ; then quit ALIGN Alignment ;------------------------------------------------------- ; ; MODE 11 OR 15: PATTERN BIC DST --> DST ; bEND11 AND.L D5,D1 ;MASK:=MASK AND LASTMASK bMAIN11 AND.L D6,D1 ;MASK PATTERN MOVE.L D1,D0 ;COPY MASKED PATTERN AND.L D4,D0 ;APPLY BK COLOR TO MASKED PATTERN NOT.L D1 ;GET NOT MASKED PATTERN AND.L (A5),D1 ;PUNCH OUT DST OR.L D1,D0 ;COMBINE SRC AND DST MOVE.L D0,(A5)+ ;PUT RESULT TO DST MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bMAIN11 ;LOOP TILL LAST LONG BEQ bEND11 ;DO LAST WITH LASTMASK BRA NXTPAT ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;------------------------------------------------------- ; ; EXPANDED PATTERN MODES ; ;----------------------------------------------------------- ; ; OPTIMIZE MODE 8 OR 12 IF DST FITS IN ONE LONG (VERT LINES ETC) ; ; <13> fix as seen in QDciPatchROM.a stb bXLONG8 AND.L alphaMask(A6),D1;clip mask with alpha mask <13> MOVE PATROW(A6),A0 ;GET PATTERN ROWBYTES MOVE PATVMASK(A6),D2 ;GET MASK FOR VERT MOVE HEIGHT(A6),D3 ;GET NUMBER OF ROWS SUBQ #1,D3 ;MAKE 0 BASED FOR DBRA LOOP addq #4,a3 ;convert dstBump to rowBytes <1.5> BAL AND.L D5,D1 ;COMBINE LEFT AND RIGHT MASKS MOVE.L D1,D5 ;COPY COMBINED MASK ADD D6,A4 ;ADD PATHPOS TO BASE clr.w D6 ;treat as unsigned <1.5> BAL SWAP D6 ;GET PATVPOS <1.5> BAL SUB.l D6,A4 ;BACK UP TO BASE OF PATTERN <1.5> BAL NOT.L D5 ;FORM NOTMASK <1.5> BAL beq.s xLong32 ;no reason to mask <1.5> BAL XLONG MOVE.L 0(A4,D6),D7 ;GET A LONG OF PATTERN AND.L D1,D7 ;MASK EXTRA PATTERN TO ZEROS MOVE.L (A5),D0 ;GET DST DATA AND.L D5,D0 ;AND WITH NOTMASK OR.L D7,D0 ;MERGE WITH SRC DATA MOVE.L D0,(A5) ;PUT RESULT TO DST ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW ADD A0,D6 ;BUMP PATTERN TO NEXT ROW AND D2,D6 ;WRAP IF PAST END OF PATTERN DBRA D3,XLONG ;LOOP ALL ROWS BRA GOHOME XLONG32 MOVE.L 0(A4,D6),(A5) ;PUT pattern TO DST <1.5> BAL ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW <1.5> BAL ADD A0,D6 ;BUMP PATTERN TO NEXT ROW <1.5> BAL AND D2,D6 ;WRAP IF PAST END OF PATTERN <1.5> BAL DBRA D3,XLONG32 ;LOOP ALL ROWS <1.5> BAL BRA GOHOME ; <1.5> BAL ;------------------------------------------------------- ; ; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES) ; PATTERN ALREADY HAS COLOR IN IT, SO NONE IS ADDED ; Doesn't handle the fits in 1 long case (see above) <1.5> BAL ; Loops for all scanlines then goes home <1.5> BAL ; ; <13> Start of alpha channel changes from QDciPatchROM.a stb bXMAIN8 TST.B alphaMode(A6) ;drawing in alpha mode? BEQ bXMAIN8G ;no, use normal loop MOVE.L alphaMask(A6),D3 ;get alpha mask AND.L D3,D1 ;AND ALPHA WITH LEFT MASK MOVE.L D1,FIRSTMASK(A6) ;SAVE THAT RESULT AND.L D3,D5 ;AND ALPHA WITH RIGHT MASK BRA.S @bX8 ;jump into alpha loop ALIGN Alignment @bXEND8 AND.L D5,D1 ;MASK:=MASK AND LASTMASK @bX8 MOVE.L 0(A4,D6),D4 ;GET PATTERN ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS MOVE.L (A5),D0 ;GET DST EOR.L D0,D4 ;APPLY DST TO PATTERN AND.L D1,D4 ;MASK OFF EDGE EOR.L D0,D4 ;REAPPLY DST MOVE.L D4,(A5)+ ;PUT RESULT TO DST MOVE.L D3,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BEQ @bXEND8 ;DO LAST LONG WITH LASTMASK BLT.S @nxtBigPat ;BUMP TO NEXT PATTERN ROW SUBQ #1,D2 ;DEC LONG COUNT NOT.L D3 ;REVERSE ALPHA MASK @alpha MOVE.L 0(A4,D6),D4 ;GET PATTERN ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS MOVE.L (A5),D0 ;GET DST EOR.L D4,D0 ;APPLY PATTERN TO DST AND.L D3,D0 ;MASK WITH ALPHA MASK EOR.L D4,D0 ;REAPPLY PATTERN MOVE.L D0,(A5)+ ;PUT RESULT TO DST DBRA D2,@alpha ;DEC LONG COUNT NOT.L D3 ;UNREVERSE ALPHA MASK BRA.S @bXEND8 ;DO LAST LONG WITH LASTMASK @nxtBigPat clr.w d6 ;make it unsigned SWAP D6 ;GET VERT POSITION IN PAT SUB.l D6,A4 ;GET BACK PAT BASE ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN ADD.l D6,A4 ;BUMP TO PROPER VERT SWAP D6 ;SAVE VERTICAL POSITION MOVE PATHPOS(A6),D6 ;INIT HORIZONTAL OFFSET ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT beq GOHOME ;LOOP FOR ALL SRCROWS MOVE.L FIRSTMASK(A6),D1 ;MASK:=FIRSTMASK MOVE LONGCNT(A6),D2 ;GET LONGCOUNT bra.s @bX8 ;go do next row ; <13> End of alpha channel changes ALIGN Alignment ;------------------------------------------------------- ; ; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES) ; PATTERN ALREADY HAS COLOR IN IT, SO NONE IS ADDED ; Doesn't handle the fits in 1 long case (see above) <1.5> BAL ; Loops for all scanlines then goes home <1.5> BAL ; bXMid8 subq #1,d2 ;make zero based for dbra <1.5> BAL @next MOVE.L 0(A4,D6),(A5)+ ;PUT PATTERN TO DST <1.5> BAL ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN <1.5> BAL AND D7,D6 ;WRAP WHEN PATTERN REPEATS <1.5> BAL dbra d2,@next ;DEC LONG COUNT <1.5> BAL bXEND8 AND.L D5,D1 ;MASK:=MASK AND LASTMASK bXMAIN8G MOVE.L D1,D0 ;COPY MASK FOR DST AND.L 0(A4,D6),D0 ;MASK PATTERN ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS NOT.L D1 ;GET NOTMASK FOR DST AND.L (A5),D1 ;PUNCH A LONG OF DST OR.L D1,D0 ;COMBINE PAT AND DST MOVE.L D0,(A5)+ ;PUT RESULT TO DST MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT bgt.s bXMid8 ;LOOP TILL LAST LONG <1.5> BAL BEQ bXEND8 ;DO LAST LONG WITH LASTMASK @nxtBigPat clr.w d6 ;make it unsigned <1.5> BAL SWAP D6 ;GET VERT POSITION IN PAT <1.5> BAL SUB.l D6,A4 ;GET BACK PAT BASE <1.5> BAL ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN <1.5> BAL AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN <1.5> BAL ADD.l D6,A4 ;BUMP TO PROPER VERT <1.5> BAL SWAP D6 ;SAVE VERTICAL POSITION <1.5> BAL MOVE PATHPOS(A6),D6 ;INIT HORIZONTAL OFFSET <1.5> BAL ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW <1.5> BAL SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT <1.5> BAL beq GOHOME ;LOOP FOR ALL SRCROWS <1.5> BAL MOVE.L FIRSTMASK(A6),D1 ;MASK:=FIRSTMASK <1.5> BAL MOVE LONGCNT(A6),D2 ;GET LONGCOUNT <1.5> BAL bra.s bXMAIN8G ;go do next row <1.5> BAL ALIGN Alignment ;------------------------------------------------------- ; ; MODE 9 OR 13: BIG PATTERN OR DST --> DST ; bXEND9 AND.L D5,D1 ;MASK:=MASK AND LASTMASK bXMAIN9 AND.L 0(A4,D6),D1 ;MASK PATTERN ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS MOVE.L D1,D0 ;COPY MASKED PATTERN AND.L D3,D0 ;APPLY FG COLOR TO MASKED PATTERN NOT.L D1 ;GET NOT MASKED PATTERN AND.L (A5),D1 ;USE TO PUNCH OUT DST OR.L D1,D0 ;COMBINE SRC AND DST MOVE.L D0,(A5)+ ;PUT RESULT TO DST MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bXMAIN9 ;LOOP TILL LAST LONG BEQ bXEND9 ;DO LAST LONG WITH LASTMASK BRA NXTBIGPAT ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;----------------------------------------------------------- ; ; OPTIMIZE MODE 10 OR 14 IF DST FITS IN ONE LONG (XOR VERT LINES) ; bXEND10 MOVE PATROW(A6),A0 ;GET PATTERN ROWBYTES <1.5> BAL MOVE PATVMASK(A6),D2 ;GET MASK FOR VERT <1.5> BAL MOVE HEIGHT(A6),D3 ;GET NUMBER OF ROWS <1.5> BAL SUBQ #1,D3 ;MAKE 0 BASED FOR DBRA LOOP <1.5> BAL addq #4,a3 ;convert dstBump to rowBytes <1.5> BAL AND.L D5,D1 ;COMBINE LEFT AND RIGHT MASKS <1.5> BAL ADD D6,A4 ;ADD PATHPOS TO BASE <1.5> BAL clr.w D6 ;treat as unsigned <1.5> BAL SWAP D6 ;GET PATVPOS <1.5> BAL SUB.l D6,A4 ;BACK UP TO BASE OF PATTERN <1.5> BAL @nxtRow MOVE.L 0(A4,D6),D0 ;Get a long of pattern <1.5> BAL AND.L D1,D0 ;Mask the pattern <1.5> BAL EOR.L D0,(A5) ;XOR RESULT INTO DST <1.5> BAL ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW <1.5> BAL ADD A0,D6 ;BUMP PATTERN TO NEXT ROW <1.5> BAL AND D2,D6 ;WRAP IF PAST END OF PATTERN <1.5> BAL DBRA D3,@nxtRow ;LOOP ALL ROWS <1.5> BAL BRA GOHOME ; <1.5> BAL ALIGN Alignment ;------------------------------------------------------- ; ; MODE 10 OR 14: BIG PATTERN XOR DST --> DST (INVERTING AREAS, XOR LINES) ; bXRGHT10 AND.L D5,D1 ;MASK:=MASK AND LASTMASK bXMAIN10 AND.L 0(A4,D6),D1 ;MASK PATTERN ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS EOR.L D1,(A5)+ ;XOR RESULT INTO DST MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bXMAIN10 ;LOOP TILL LAST LONG BEQ bXRGHT10 ;DO LAST LONG WITH LASTMASK BRA NXTBIGPAT ;LOOP BACK FOR NEXT ROW ALIGN Alignment ;------------------------------------------------------- ; ; MODE 11 OR 15: BIG PATTERN BIC DST --> DST ; bXEND11 AND.L D5,D1 ;MASK:=MASK AND LASTMASK bXMAIN11 AND.L 0(A4,D6),D1 ;MASK PATTERN ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN AND D7,D6 ;WRAP WHEN PATTERN REPEATS MOVE.L D1,D0 ;COPY MASKED PATTERN AND.L D4,D0 ;APPLY BK COLOR TO MASKED PATTERN NOT.L D1 ;GET NOT MASKED PATTERN AND.L (A5),D1 ;PUNCH OUT DST OR.L D1,D0 ;COMBINE SRC AND DST MOVE.L D0,(A5)+ ;PUT RESULT TO DST MOVEQ #-1,D1 ;FLUSH MASK SUB #1,D2 ;DEC LONG COUNT BGT bXMAIN11 ;LOOP TILL LAST LONG BEQ bXEND11 ;DO LAST WITH LASTMASK BRA NXTBIGPAT ;LOOP BACK FOR NEXT ROW if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; arithSetup32 ; (SP) hbump for a pixel ; A0 inverse color table ; A1 modeCase ; D0 first destination/mask pixel position ; D2 number of pixels in a long, or 0 if only 1 long ; D5 inverse color table entry size ; D6 first source pixel position ; D7 pixel size ; doneMid(A6) cleared (byte) ; lastMask(A6) equal to D5 standard ; midCount(A6) equal to # of pixels on line less mask longs ; pixInLong(A6) equal to # of pixels in a long bArith32Setup move.w destPixCnt(a6),d2 ;get # pixels to blit <1.5> BAL subq.w #1,d2 ;make zero based for dbra <1.5> BAL move.w d2,longcnt(a6) ;remember for later <1.5> BAL moveq #0,d4 ;patHMask should be a long move.w patHMask(a6),d4 ;get pattern index mask lsr.l #3,d4 ;make byte mask move.w d4,patHMask(a6) ;save for subover TST.B endSwitch(A6) ;is the src a pattern? bpl.s @usePat moveq #0,d6 ;no, clear pattern index @usePat lsr.l #3,d6 ;make byte offset MOVE.L d6,patOffset(A6) ;save for subsequent scans move.w srcrow+2(a6),srcbump(a6) move.w hBump(a6),a3 ;set up hBump in a3 (±4) move.w a3,d7 ;are we bumping right to left? bpl.s @goBlit addq.w #1,d2 ;bump cnt move.w d2,longcnt(a6) ;remember for later @goBlit jmp (a1) ;take modecase ALIGN Alignment ;------------------------------------------------------- ; a4 = srcPtr/patPtr d1 = leftMask ; a5 = dstPtr bArith16Setup move.w destPixCnt(a6),d2 ;get # pixels to blit subq.w #1,d2 ;make zero based for dbra move.w d2,longcnt(a6) ;remember for later ; TST.B endSwitch(A6) ;is the src a pattern? ; bpl.s @usePat ; moveq #0,d6 ;no, clear pattern index ;usePat asr.l #3,d6 ;make byte offset MOVE.L d6,patOffset(A6) ;save for subsequent scans move.w srcrow+2(a6),srcbump(a6) move.w hBump(a6),d7 ;are we bumping right to left? asr.w #1,d7 ;convert to word bump (±2) move.w d7,a3 ;setup hbump in a3 bpl.s @RtoL addq.w #1,d2 ;bump cnt move.w d2,longcnt(a6) ;remember for later @RtoL tst.l d1 ;should we blit first pixel? bmi.s @leftOK ;yes, ptrs are ok addq #2,a5 ;bump dstptr addq.l #2,d6 ;bump src index MOVE.L d6,patOffset(A6) ;save for subsequent scans @leftOK moveq #0,d4 ;patHMask should be a long move.w patHMask(a6),d4 ;get pattern index mask lsr.l #3,d4 ;make long mask bset #1,d4 ;make word mask move.w d4,patHMask(a6) ;save for subover jmp (a1) ;take modecase else ;<14> bArith32Setup bArith16Setup ; _Debugger endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 34, 42, 58: SRC + DST --> DST (no pin) ; (SP) hbump for a pixel ; A0 inverse color table ; A1 color table ; D0 first destination/mask pixel position ; D2 number of pixels in a long, or 0 if only 1 long ; D5 inverse color table entry size ; D6 first source pixel position ; D7 pixel size ; doneMid(A6) cleared (byte) ; lastMask(A6) equal to D5 standard ; midCount(A6) equal to # of pixels on line less mask longs ; pixInLong(A6) equal to # of pixels in a long ; note: D4 is unused bAddOver bAddOverIndexed ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbAddOver1 ; <14AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> @RealbAddOver tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbAddOver1 ; <14AUG90 KON> sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbAddOver1 MOVE.L colorTable(A6),A1 ;set up color table TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) LEA red(A1,D3*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D0:D7},D3 ;a pixel of the destination LEA red(A1,D3*8),A3 ;figure out where destination lives MOVE (A2)+,D3 ;red get source color value ADD (A3)+,D3 ; combine source and destination ASL.L D5,D3 ; save the top bits in the top word MOVE (A2)+,D3 ;green get source color value ADD (A3)+,D3 ; combine source and destination ASL.L D5,D3 ; save the top bits in the top word MOVE (A2)+,D3 ;blue get source color value ADD (A3)+,D3 ; combine source and destination ASL.L D5,D3 ; save the top bits in the top word SWAP D3 ;r, g, b in high word MOVE.B itTable(A0,D3),D3 ;get the pixel value of the additive sum BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it lea @RealbAddOver,A1 ;restore address to ourselves <14AUG90 KON> BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit clearing mask ; a1 = modeCase/mask d1 = dst msb's ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = src msb's ; a4 = srcPtr/patPtr d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7^= patHBump d7 = src pixel ;------------------------------------------------------- bAddOver32 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.l #~$ff808080,d0 ;get high bit clearing mask move.l #$00808080,a1 ;get high bit mask @loopTop move.l a1,d3 ;copy high bit mask move.l (a0),d7 ;get a pixel of the source xrgb and.l d7,d3 ;remember src msb's add.w a3,a0 ;bump bidirectionally and.l d0,d7 ;mask out stragglers move.l (a2),d5 ;get a pixel of the dest xrgb move.l a1,d1 ;copy high bit mask and.l d5,d1 ;remember dst msb's and.l d0,d5 ;mask out stragglers add.l d5,d7 ;merge src with dst eor.l d3,d1 ;compute partial sum of msb's eor.l d1,d7 ;compute partial sum of msb's move.l d7,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally addq.l #4,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line lea bAddOver32,a1 ;reload modeCase BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit clearing mask ; a1 = modeCase/mask d1 = dst msb's ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = src msb's ; a4 = srcPtr/patPtr d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7^= patHBump d7 = src pixel ;------------------------------------------------------- bAddOver16 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.w #$3def,d0 ;get high bit clearing mask move.w #$4210,a1 ;get high bit mask @loopTop move.w a1,d3 ;copy high bit mask move.w (a0),d7 ;get a pixel of the source xrgb and.w d7,d3 ;remember src msb's add.w a3,a0 ;bump bidirectionally and.w d0,d7 ;mask out stragglers move.w (a2),d5 ;get a pixel of the dest xrgb move.w a1,d1 ;copy high bit mask and.w d5,d1 ;remember dst msb's and.w d0,d5 ;mask out stragglers add.w d5,d7 ;merge src with dst eor.w d3,d1 ;compute partial sum of msb's eor.w d1,d7 ;compute partial sum of msb's move.w d7,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally addq.l #2,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line lea bAddOver16,a1 ;reload modeCase BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 33, 41, 57: SRC + DST --> DST (pin to max) ; in addition to the registers set up for Mode 17 (AddOver), this needs ; the 3 element word array pin(A6) to be set to the maximum b, g, r values (in that order) ; for comparison and pinning ; Note that D4 is unused bAddPin bAddPinIndexed ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbAddPin1 ; <14AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> @RealbAddPin tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbAddPin1 ; <14AUG90 KON> sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbAddPin1 MOVE.L colorTable(A6),A1 ;set up color table TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) LEA red(A1,D3*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D0:D7},D3 ;a pixel of the destination LEA red(A1,D3*8),A3 ;figure out where destination lives MOVE (A2)+,D3 ;get source color value ADD (A3)+,D3 ;combine source and destination BCS.S @tooBigRed CMP pin+4(A6),D3 ;bigger than pin value? BLS.S @notTooBigRed ;no, no problem @tooBigRed MOVE pin+4(A6),D3 @notTooBigRed ASL.L D5,D3 ;save the top bits in the top word MOVE (A2)+,D3 ;get source color value ADD (A3)+,D3 ;combine source and destination BCS.S @tooBigGreen CMP pin+2(A6),D3 ;bigger than pin value? BLS.S @notTooBigGreen ;no, no problem @tooBigGreen MOVE pin+2(A6),D3 @notTooBigGreen ASL.L D5,D3 ;save the top bits in the top word MOVE (A2)+,D3 ;get source color value ADD (A3)+,D3 ;combine source and destination BCS.S @tooBigBlue CMP pin(A6),D3 ;bigger than pin value? BLS.S @notTooBigBlue ;no, no problem @tooBigBlue MOVE pin(A6),D3 @notTooBigBlue ASL.L D5,D3 ;save the top bits in the top word SWAP D3 ;r, g, b in high word MOVE.B itTable(A0,D3),D3 ;get the pixel value of the additive sum BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it lea @RealbAddPin,A1 ;restore address to ourselves <14AUG90 KON> BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = lo3Bytes mask ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = pin pixel 0rgb ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = dst long ; a6 = locals d6 = pat offset (bytes) ; a7^= d7 = src long ;------------------------------------------------------- bAddPin32 ;set up pin pixel as 0rgb in D3 -> overwrites pattern bump lea bAddPin32Main,A1 ;go there from now on 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 bAddPin32Main move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.l Lo3Bytes,d1 ;pick up mask @loopTop move.l (a0),d7 ;get a pixel of the source xrgb and.l d1,d7 ;waste high byte move.l d7,d0 ;make a copy of the src xrgb add a3,a0 ;bump bi-directionally move.l (a2),d5 ;get a pixel of the dest xrgb 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,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #4,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = lo3Bytes mask ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = pin pixel 0rgb ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = dst long ; a6 = locals d6 = pat offset (bytes) ; a7^= d7 = src long ;------------------------------------------------------- bAddPin16 lea bAddPin16Main,A1 ;go here from now on 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 bAddPin16Main move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr @loopTop moveq #0,d7 move.w (a0),d7 ;get a pixel of the source xrgb add a3,a0 ;bump bi-directionally 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 (a2),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,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #2,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 38, 46, 62: DST - SRC --> DST (no pin) ; ; Note that D4 is unused bSubOver bSubOverIndexed ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbSubOver1 ; <14AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> @RealbSubOver tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbSubOver1 ; <14AUG90 KON> sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbSubOver1 MOVE.L colorTable(A6),A1 ;set up color table TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) LEA red(A1,D3*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D0:D7},D3 ;a pixel of the destination LEA red(A1,D3*8),A3 ;figure out where destination lives MOVE (A3)+,D3 ;get destination SUB (A2)+,D3 ;less source color value ASL.L D5,D3 ;save the top 4 bits in the top word MOVE (A3)+,D3 ;get destination SUB (A2)+,D3 ;less source color value ASL.L D5,D3 ;save the top 4 bits in the top word MOVE (A3)+,D3 ;get destination SUB (A2)+,D3 ;less source color value ASL.L D5,D3 ;save the top 4 bits in the top word SWAP D3 ;r, g, b in high word MOVE.B itTable(A0,D3),D3 ;get the pixel value of the additive sum BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it lea @RealbSubOver,A1 ;restore address to ourselves <14AUG90 KON> BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit clearing mask ; a1 = modeCase d1 = high bit mask ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = src msb's ; a4 = srcPtr/patPtr d4 = dst msb's ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7^= d7 = src pixel ;------------------------------------------------------- bSubOver32 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.l #~$ff808080,d0 ;get high bit clearing mask move.l #$00808080,d1 ;get high bit mask @loopTop move.l d1,d3 ;copy high bit mask move.l (a0),d7 ;get a pixel of the source xrgb and.l d7,d3 ;remember src msb's eor.l d1,d3 ;invert src msb's add.w a3,a0 ;bump bidirectionally and.l d0,d7 ;mask out stragglers move.l (a2),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,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally addq.l #4,d6 ;bump pattern offset and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit clearing mask ; a1 = modeCase d1 = high bit mask ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = src msb's ; a4 = srcPtr/patPtr d4 = dst msb's ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7^= d7 = src pixel ;------------------------------------------------------- ; as seen in QDciPatchROM.a stb bSubOver16 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.w #$3def,d0 ;get high bit clearing mask move.w #$4210,d1 ;get high bit mask @loopTop move.w d1,d3 ;copy high bit mask move.w (a0),d7 ;get a pixel of the source xrgb add.w a3,a0 ;bump bidirectionally 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 (a2),d5 ;get a pixel of the dest xrgb <11> 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,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally addq.l #2,d6 ;bump pattern offset and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 35, 43, 59: DST - SRC --> DST (pin to min) bSubPin bSubPinIndexed ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbSubPin1 ; <14AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> @RealbSubPin tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbSubPin1 ; <14AUG90 KON> sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbSubPin1 MOVE.L colorTable(A6),A1 ;set up color table TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) LEA red(A1,D3*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D0:D7},D3 ;a pixel of the destination LEA red(A1,D3*8),A3 ;figure out where destination lives MOVE (A3)+,D3 ;destination color SUB (A2)+,D3 ;less source color value BCS.S @tooBigRed CMP pin+4(A6),D3 ;smaller than pin value? BHS.S @notTooBigRed ;no, no problem @tooBigRed MOVE pin+4(A6),D3 @notTooBigRed ASL.L D5,D3 ;save the top 4 bits in the top word MOVE (A3)+,D3 ;destination color SUB (A2)+,D3 ;less source color value BCS.S @tooBigGreen CMP pin+2(A6),D3 ;smaller than pin value? BHS.S @notTooBigGreen ;no, no problem @tooBigGreen MOVE pin+2(A6),D3 @notTooBigGreen ASL.L D5,D3 ;save the top 4 bits in the top word MOVE (A3)+,D3 ;destination color SUB (A2)+,D3 ;less source color value BCS.S @tooBigBlue CMP pin(A6),D3 ;smaller than pin value? BHS.S @notTooBigBlue ;no, no problem @tooBigBlue MOVE pin(A6),D3 @notTooBigBlue ASL.L D5,D3 ;save the top 4 bits in the top word SWAP D3 ;r, g, b in high word MOVE.B itTable(A0,D3),D3 ;get the pixel value of the additive sum BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it lea @RealbSubPin,A1 ;restore address to ourselves <14AUG90 KON> BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = lo3Bytes mask ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = pin pixel 0rgb ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = src long ; a6 = locals d6 = pat offset (bytes) ; a7^= d7 = dst long ;------------------------------------------------------- ;set up pin pixel as 0rgb in D3 -> overwrites pattern bump bSubPin32 lea bSubPin32Main,A1 ;go there from now on 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 bSubPin32Main move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.l Lo3Bytes,d1 ;pick up mask @loopTop move.l (a0),d5 ;get a pixel of the source xrgb and.l d1,d5 ;waste high byte add a3,a0 ;bump bi-directionally move.l (a2),d7 ;get a pixel of the dest xrgb 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,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #4,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = borrow stopper ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = pin pixel 0rgb ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = src long ; a6 = locals d6 = pat offset (bytes) ; a7^= d7 = dst long ;------------------------------------------------------- bSubPin16 lea bSubPin16Main,A1 ;go there from now on 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 bSubPin16Main move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.l #$808080,d1 ;borrow stopper @loopTop moveq #0,d5 move.w (a0),d5 ;get a pixel of the source xrgb add a3,a0 ;bump bi-directionally 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 (a2),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,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #2,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 37, 45, 61: MAX(SRC, DST) --> DST ; ; Note: D4 is unused bMax bMaxIndexed ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbMax1 ; <14AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> @RealbMax tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbMax1 ; <14AUG90 KON> sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbMax1 MOVE.L colorTable(A6),A1 ;set up color table TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) LEA red(A1,D3*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D0:D7},D3 ;a pixel of the destination LEA red(A1,D3*8),A3 ;figure out where destination lives MOVE (A2)+,D3 ;get source color value CMP (A3),D3 ;combine source and destination BHS.S @gotTheMaxRed MOVE (A3),D3 @gotTheMaxRed ADDQ #2,A3 ;advance to next color ASL.L D5,D3 ;save the top bits in the top word MOVE (A2)+,D3 ;get source color value CMP (A3),D3 ;combine source and destination BHS.S @gotTheMaxGreen MOVE (A3),D3 @gotTheMaxGreen ADDQ #2,A3 ;advance to next color ASL.L D5,D3 ;save the top bits in the top word MOVE (A2)+,D3 ;get source color value CMP (A3),D3 ;combine source and destination BHS.S @gotTheMaxBlue MOVE (A3),D3 @gotTheMaxBlue ASL.L D5,D3 ;save the top bits in the top word SWAP D3 ;r, g, b in high word MOVE.B itTable(A0,D3),D3 ;get the pixel value of the additive sum BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it lea @RealbMax,A1 ;restore address to ourselves <14AUG90 KON> BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = patHBump (bytes) ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = dst long ; a6 = locals d6 = pat offset (bytes) ; a7 = d7 = src long ;------------------------------------------------------- bMax32 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr @loopTop move.l (a0),d7 ;get a pixel of the source xrgb add a3,a0 ;bump bi-directionally move.l (a2),d5 ;get a pixel of the dest xrgb move.l d5,d0 ;make a copy of the dest xrgb cmp.w d7,d0 ;compare g,b components BHI.S @gotTheMaxGreen move.w d7,d0 ;keep the bigger of the two move.b d5,d0 ;prime for blue @gotTheMaxGreen cmp.b d7,d5 ;compare blue components BHI.S @gotTheMaxBlue move.b d7,d0 ;keep the bigger of the two @gotTheMaxBlue swap d7 swap d0 cmp.b d7,d0 ;compare red components BHI.S @gotTheMaxRed move.b d7,d0 ;keep the bigger of the two @gotTheMaxRed swap d0 ;get new xrgb move.l d0,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #4,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = patHBump (bytes) ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = dst long ; a6 = locals d6 = pat offset (bytes) ; a7 = d7 = src long ;------------------------------------------------------- bMax16 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr @loopTop moveq #0,d7 move.w (a0),d7 ;get a pixel of the source xrgb add a3,a0 ;bump bi-directionally 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 (a2),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,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #2,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 39, 47, 63: MIN(SRC, DST) --> DST ; ; Note: D4 is unused bMin bMinIndexed ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbMin1 ; <14AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> @RealbMin tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbMin1 ; <14AUG90 KON> sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbMin1 MOVE.L colorTable(A6),A1 ;set up color table TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) LEA red(A1,D3*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D0:D7},D3 ;a pixel of the destination LEA red(A1,D3*8),A3 ;figure out where destination lives MOVE (A2)+,D3 ;get source color value CMP (A3),D3 ;combine source and destination BLS.S @gotTheMinRed MOVE (A3),D3 @gotTheMinRed ADDQ #2,A3 ;advance to next color ASL.L D5,D3 ;save the top bits in the top word MOVE (A2)+,D3 ;get source color value CMP (A3),D3 ;combine source and destination BLS.S @gotTheMinGreen MOVE (A3),D3 @gotTheMinGreen ADDQ #2,A3 ;advance to next color ASL.L D5,D3 ;save the top bits in the top word MOVE (A2)+,D3 ;get source color value CMP (A3),D3 ;combine source and destination BLS.S @gotTheMinBlue MOVE (A3),D3 @gotTheMinBlue ASL.L D5,D3 ;save the top bits in the top word SWAP D3 ;r, g, b in high word MOVE.B itTable(A0,D3),D3 ;get the pixel value of the additive sum BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it lea @RealbMin,A1 ;restore address to ourselves <14AUG90 KON> BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = patHBump (bytes) ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = dst long ; a6 = locals d6 = pat offset (bytes) ; a7 = d7 = src long ;------------------------------------------------------- bMin32 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr @loopTop move.l (a0),d7 ;get a pixel of the source xrgb add a3,a0 ;bump bi-directionally move.l (a2),d5 ;get a pixel of the dest xrgb move.l d5,d0 ;make a copy of the dest xrgb cmp.w d7,d0 ;compare g,b components BLS.S @gotTheMinGreen move.w d7,d0 ;keep the smaller of the two move.b d5,d0 ;prime for blue @gotTheMinGreen cmp.b d7,d5 ;compare blue components BLS.S @gotTheMinBlue move.b d7,d0 ;keep the smaller of the two @gotTheMinBlue swap d7 swap d0 cmp.b d7,d0 ;compare red components BLS.S @gotTheMinRed move.b d7,d0 ;keep the smaller of the two @gotTheMinRed swap d0 ;get new xrgb move.l d0,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #4,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = result/scratch ; a1 = modeCase d1 = ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = patHBump (bytes) ; a4 = srcPtr/patPtr d4 = patHMask (bytes) ; a5 = dstPtr d5 = dst long ; a6 = locals d6 = pat offset (bytes) ; a7 = d7 = src long ;------------------------------------------------------- bMin16 move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr @loopTop moveq #0,d7 move.w (a0),d7 ;get a pixel of the source xrgb add a3,a0 ;bump bi-directionally 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 (a2),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 smaller? 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 smaller? 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 smaller? 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,(a2) ;move to the destination add a3,a2 ;bump bi-directionally addq.l #2,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 32, 40, 56: AVG(SRC, DST, WEIGHT) --> DST bAvg bAvgIndexed ; ; if we are going backwards, align destination and mask <13AUG90 KON> ; tst (sp) ;is bump amount negative? <13AUG90 KON> bpl.s @RealbAvg1 ; <13AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <13AUG90 KON> @RealbAvg tst (sp) ;is bump amount negative? <13AUG90 KON> bpl.s @RealbAvg1 ; <13AUG90 KON> sub.l (SP),D0 ;align destination and mask each scan line <13AUG90 KON> @RealbAvg1 MOVE.L colorTable(A6),A1 ;set up color table TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) LEA red(A1,D3*8),A2 ;figure out where it lives in the color table BFEXTU (A5){D0:D7},D3 ;a pixel of the destination LEA red(A1,D3*8),A3 ;figure out where destination lives MOVE.l D0,-(SP) ;preserve mask/destination offset <13AUG90 KON> MOVEQ #2,D0 ;once for each color MOVE invSize(A6),D4 ;do once for r, b and g ADD D4,D4 ;initialize at 2x for shift count CLR -(SP) ;make space & initialize average r, b, g @nextColor MOVE (A2)+,D3 ;get source color value MULU (weight,A6,D0*2),D3 ;weight varies from 0 to 1 MOVE (A3)+,D5 ;get destination color value MULU (notWeight,A6,D0*2),D5 ;weight varies from 1 to 0 ADD.L D5,D3 ;add source + dest SWAP D3 ;high word is interesting part MOVE rtShift(A6),D5 ;amount to shift right LSR D5,D3 ;get top bits only LSL D4,D3 ;shift by 2x, 1x, or 0 (for r, g, & b) OR D3,(SP) ;combine r, g, b SUB invSize(A6),D4 ;decrement shift, weight index DBRA D0,@nextColor ;do for b & g as well MOVE (SP)+,D3 ;r, g, b MOVE.l (SP)+,D0 ;restore mask/destination offset <13AUG90 KON> MOVE.B itTable(A0,D3),D3 ;get the pixel value of the additive sum BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it lea @RealbAvg,a1 ;from now on, enter at @RealbAvg <13AUG90 KON> BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit mask ; a1 = modeCase d1 = low bit mask ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = lsb's of result ; a4 = srcPtr/patPtr d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7^= patHBump d7 = src pixel ;------------------------------------------------------- bAvg32Half move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.l #~$ff808080,d0 ;get high bit mask move.l #$10101,d1 ;get low bit mask @loopTop move.l d1,d3 ;copy low bit mask move.l (a0),d7 ;get a pixel of the source xrgb and.l d7,d3 ;remember src lsb's add.w a3,a0 ;bump bidirectionally lsr.l #1,d7 ;get almost 1/2 of it and.l d0,d7 ;mask out stragglers move.l (a2),d5 ;get a pixel of the dest xrgb 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,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally addq.l #4,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit mask ; a1 = modeCase d1 = low bit mask ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = lsb's of result ; a4 = srcPtr/patPtr d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7^= patHBump d7 = src pixel ;------------------------------------------------------- bAvg16Half move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.w #$3def,d0 ;get high bit clearing mask move.w #$0421,d1 ;get low bit mask @loopTop move.l d1,d3 ;copy low bit mask move.w (a0),d7 ;get a pixel of the source xrgb and.w d7,d3 ;remember src lsb's add.w a3,a0 ;bump bidirectionally lsr.w #1,d7 ;get almost 1/2 of it and.w d0,d7 ;mask out stragglers move.w (a2),d5 ;get a pixel of the dest xrgb 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,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally addq.l #2,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = red weight ; a1 = last dst/mcase d1 = blue/grn weight ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = scratch ; a4 = srcPtr/patPtr d4 = scratch ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7 = d7 = src pixel ;------------------------------------------------------- bAvg32 lea weight(a6),a0 ;point at blue weight move.l (a0)+,d1 ;get blue/green weight move.w (a0),d0 ;get red weight move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr @short0 moveq #0,d4 ;init last result move.l d4,d3 ;init last src move.l d4,a1 ;init last dst @loopTop move.l (a0),d7 ;get a pixel of the source xrgb add.w a3,a0 ;bump bidirectionally for MCF move.l (a2),d5 ;get a pixel of the dest xrgb @short1 cmp.l d3,d7 ;same as last time? bne.s @blue ;no, go do it cmp.l a1,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,a1 ;a1 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,a1 ;a1 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 a1,d4 ;d4 has 0RGB @short2 swap d5 ;get back dst move.l d5,a1 ;save for short circuit swap d7 ;get back src move.l d7,d3 ;save for short circuit @again move.l d4,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally for MCF addq.w #4,d6 ;bump horizontally in pattern and.w patHMask(a6),d6 ;force pattern offset to wrap bne.s @patOK move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line lea bAvg32,a1 ;reload modecase BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = red weight ; a1 = last dst/mcase d1 = blue/grn weight ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = scratch ; a4 = srcPtr/patPtr d4 = scratch ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7 = d7 = src pixel ;------------------------------------------------------- bAvg16 lea weight(a6),a0 ;point at blue weight move.l (a0)+,d1 ;get blue/green weight move.w (a0),d0 ;get red weight move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr @short0 moveq #0,d4 ;init last result move.l d4,d3 ;init last src move.l d4,a1 ;init last dst @loopTop moveq #0,d7 move.w (a0),d7 ;get a pixel of the source xrgb add.w a3,a0 ;bump bidirectionally for MCF moveq #0,d5 move.w (a2),d5 ;get a pixel of the dest xrgb @short1 cmp.w d3,d7 ;same as last time? bne.s @hardway ;no, go do it cmp.w a1,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,a1 ;a1 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,a1 ;a1 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 a1,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,a1 ;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,(a2) ;move to the destination add.w a3,a2 ;bump bidirectionally for MCF addq.w #2,d6 ;bump horizontally in pattern and.w patHMask(a6),d6 ;force pattern offset to wrap bne.s @patOK move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line lea bAvg16,a1 ;reload modecase BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; MODE 50: Hilite DST (similar to invert) ; if dst = background, foreground color -> background ; if dst = foreground color, background -> foreground color ; do a long at a time when possible ; ;input ; D0 background pixel D1 mask D2 long count D3 --- ; D4 background long D5 foreground pixel D6 --- D7 pixel size ; A0 foreground long A1 --- A2 32-pixel size A3 --- ; A4 --- A5 destination pointer ;registers used: ; D3 scratch D6 scratch ;locals used: ; lastMask(A6) the right most long mask bHilite SUBQ #1,D2 ;more than 1 long? BMI.S @lastMask ;if only 1 long, just do last mask & first mask BSR.S hiliteMask ;mask off first part SUBQ #1,D2 ;make inner loop DBRA count BMI.S @fullMask ;if only left and right, skip middle part of loop @nextLong CMP.L (A5),D4 ;is the next long the same as the background? BNE.S @oneAtATime @midSwitch MOVE.L A0,(A5)+ ;save a long of the hilite color @midLoop DBRA D2,@nextLong ;do the next one @fullMask MOVEQ #-1,D1 ;flush mask for end10 @lastMask AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK BSR.S hiliteMask BRA NxtSrc @oneAtATime CMP.L (A5),A0 BEQ.S @switch ; first see if it is the same as the "other" color MOVE.L A2,D6 ;initial long position count @nextPixel BFEXTU (A5){D6:D7},D3 ;get a pixel of the destination CMP.l D3,D0 ;same as the background color? BNE.S @tryNew BFINS D5,(A5){D6:D7} BRA.S @skipToNext @tryNew CMP.l D5,D3 ;same as new color? BNE.S @skipToNext BFINS D0,(A5){D6:D7} @skipToNext SUB D7,D6 ;advance to next pixel BPL.S @nextPixel ADDQ #4,A5 BRA.S @midLoop @switch BFEXTU D4{0:D7},D5 ;set up a pixel sized highlight color EXG A0,D4 ;switch the highlight color w/ the background color BFEXTU D4{0:D7},D0 ;and a pixel sized background color BRA.S @midSwitch hiliteMask MOVE.L D4,D3 ;get a long of background AND.L D1,D3 ;mask background to right mask MOVE.L (A5),D6 ;get a long of dst AND.L D1,D6 ;mask it as well CMP.L D3,D6 ;the same? BNE.S @oneAtATime ;no, must do left part 1 pixel at a time MOVE.L A0,D3 ;get the hilite color AND.L D1,D3 ;mask it NOT.L D1 ;flip the mask AND.L (A5),D1 ;get the data already there OR.L D3,D1 ;combine the two together MOVE.L D1,(A5)+ ;deposit the result and move on RTS @oneAtATime ; first see if it is the same as the "other" color MOVE.L A2,D6 ;start at last pixel position @nextPixel BFEXTU D1{D6:D7},D3 ;a pixel of the mask BEQ.S @skipBlank ;if nothing, skip it BFEXTU (A5){D6:D7},D3 ;get a pixel of the destination CMP.l D3,D0 ;same as the background color? BNE.S @tryNew BFINS D5,(A5){D6:D7} BRA.S @skipToNext @tryNew CMP.l D5,D3 ;same as new color? BNE.S @skipToNext BFINS D0,(A5){D6:D7} @skipToNext @skipBlank SUB D7,D6 ;advance to next pixel BPL.S @nextPixel ADDQ #4,A5 RTS if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; chosen if the dst is 32 bits/pixel ; bHilite32 MOVEQ #-1,D0 LSR.L #8,D0 ;get low3byte mask in d0 MOVE D2,D3 ;save a copy in d3 @nxtScan MOVE D3,D2 ;reset longCnt @nextLong MOVE.L D0,D1 ;copy pixel mask AND.L (A5),D1 ;remove alpha byte CMP.L D1,D4 ;is the next long the same as the background? BNE.S @chkOther @midSwitch MOVE.L A0,(A5)+ ;save a long of the hilite color DBRA D2,@nextLong ;do the next one BRA.S @NxtDst @chkOther CMP.L D1,A0 BNE.S @next EXG A0,D4 ;switch the highlight color w/ the background color BRA.S @midSwitch @next ADDQ #4,A5 DBRA D2,@nextLong ;do the next one @NxtDst ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT BNE.S @nxtScan ;LOOP FOR ALL SRCROWS BRA.S GOHOME ;THEN QUIT endif ;<14> ALIGN Alignment ;------------------------------------------------------- ; ; chosen if the source was not a small pattern equal to black, so does not look for long ; optimizations ; ; fix from QDciPatchROM.a stb ; handle vertically aligned hilites (like that ever happens) and ; preserve a non-white background color through the entire blit (more common). <14SEP90 SMC> bSloHilite ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; lea @RealbSloHilite1,a1 ; <13SEP90 SMC> BFEXTU D4{0:D7},D4 ;set up pixel of the background color <13SEP90 SMC> tst (sp) ;is bump amount negative? <14AUG90 KON> bpl.s @RealbSloHilite1 ; <14AUG90 KON> sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> lea @RealbSloHilite,a1 ;remember correct entry point for remaining scans <14AUG90 KON> @RealbSloHilite sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbSloHilite1 cmp.w #32,d7 ;1 pixel per long? <08Jan89 BAL> beq.s @firstMask ;yes, d2 is unfortunately zero <08Jan89 BAL> TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) CMP.l D3,D4 ;same as the background color? <08Jan89 BAL> BEQ.S @skip BFEXTU (A5){D0:D7},D3 ;get a pixel of the destination CMP.l D3,D4 ;same as the background color? <08Jan89 BAL> BNE.S @tryNew BFINS D5,(A5){D0:D7} BRA.S @skip @tryNew CMP.l D5,D3 ;same as new color? BNE.S @skip BFINS D4,(A5){D0:D7} @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it BRA NxtNewSrc ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; ; MODES 36, 44, 60: SRC less bg --> DST ; (SP) hbump for a pixel ; A2 32 correctly signed ; D0 first destination/mask pixel position ; D2 number of pixels in a long, or 0 if only 1 long ; D4 background long ; D5 one background pixel ; D6 first source pixel position ; D7 pixel size ; doneMid(A6) cleared (byte) ; lastMask(A6) equal to D5 standard ; midCount(A6) equal to # of pixels on line less mask longs ; pixInLong(A6) equal to # of pixels in a long bTransparent ; ; if we are going backwards, align destination and mask <14AUG90 KON> ; ; rolled in SMC’s changes from QDciPatchROM.a stb lea @RealbTransparent1,a1 ; <26SEP90 SMC> <10> tst.l (sp) ;is bump amount negative? <14AUG90 KON> bmi.s @1 ; <14AUG90 KON> CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? <08Oct90 SMC> <72> BEQ bTransparent8 ; <08Oct90 SMC> <72> BRA.S @RealbTransparent1 ; <08Oct90 SMC> <72> @1: sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON> lea @RealbTransparent,a1 ;remember correct entry point for remaining scans <14AUG90 KON> @RealbTransparent sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON> @RealbTransparent1 cmp.w #32,d7 ;1 pixel per long? <08Jan89 BAL> beq.s @firstMask ;yes, d2 is unfortunately zero <08Jan89 BAL> TST D2 ;is there only 1 long? BGT.S @firstMask ;if not, use the first mask in D1 @forceLast OR.B #3,doneMid(A6) ;note that the first part and mid part are done @lastMask MOVE pixInLong(A6),D2 ;loop once for each pixel in the long AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK @firstMask @loopTop AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode BFEXTU D1{D0:D7},D3 ;a pixel of the mask BEQ.S @skip BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word) CMP.L D3,A3 ;same as a pixel of the background? BEQ.S @skip BFINS D3,(A5){D0:D7} ;move to the destination @skip ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel ADD.L (SP),D0 ;bump destination and mask DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask) @loopEnd ADDQ #1,D2 ;check to see if we ended on a natural long BEQ.S @noPixelAlign ;if so, expect a -1 here SUB.L (SP),D6 ;unbump source SUB.L (SP),D0 ;unbump destination BRA.S @loopEnd @noPixelAlign MOVEQ #-1,D1 ;flush mask BSET #0,doneMid(A6) ;has the middle part already been done? BNE.S @midDone ;if so, skip it MOVE midCount(A6),D2 ;reset to mid count BMI.S @forceLast ;if none, just do the last part BRA.S @loopTop @midDone BSET #1,doneMid(A6) ;already done the last mask part too? BEQ.S @lastMask ;if not, do it BRA NxtNewSrc ;LOOP BACK FOR MORE if blit32 then ;<14> ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high byte clearing mask ; a1 = modeCase d1 = ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = transColor (long) ; a4 = srcPtr/patPtr d4 = patHMask ; a5 = dstPtr d5 = ; a6 = locals d6 = pat offset ; a7^= patHBump d7 = src pixel ;------------------------------------------------------- bTransparent32 MOVE.L BCOLOR(A6),D3 ;GET BKCOLOR (transColor if arithmetic mode) move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr move.l maskBC,d0 ;get high byte clearing mask @loopTop move.l (a0),d7 ;get a pixel of the source xrgb add.w a3,a0 ;bump bidirectionally and.l d0,d7 ;mask off high byte cmp.l d3,d7 ;same as transparent color? beq.s @skip move.l d7,(a2) ;move to the destination @skip add.w a3,a2 ;bump bidirectionally addq.l #4,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE ALIGN Alignment ;------------------------------------------------------- ; a0 = tmpsrc d0 = high bit clearing mask ; a1 = modeCase d1 = ; a2 = tmpdst d2 = longCnt ; a3 = hBump d3 = ; a4 = srcPtr/patPtr d4 = patHMask ; a5 = dstPtr d5 = dest pixel ; a6 = locals d6 = pat offset ; a7^= patHBump d7 = src pixel ;------------------------------------------------------- bTransparent16 MOVE.L BCOLOR(A6),D3 ;GET BKCOLOR (transColor if arithmetic mode) move.l a4,a0 ;get working copy of srcptr add.w d6,a0 ;index into pattern move.l a5,a2 ;get working copy of dstptr moveq #-1,d0 ;get high bit clearing mask lsr.w #1,d0 @loopTop move.w (a0),d7 ;get a pixel of the source xrgb add.w a3,a0 ;bump bidirectionally and.w d0,d7 ;mask off high bit cmp.w d3,d7 ;same as transparent color? beq.s @skip move.w d7,(a2) ;move to the destination @skip add.w a3,a2 ;bump bidirectionally addq.l #2,d6 ;bump pattern offset and.l d4,d6 ;constrict to the source long if in a pattern mode bne.s @patOK ;don't need to reload pat ptr move.l a4,a0 ;reload pat ptr @patOK DBRA D2,@loopTop ;do it for all pixels on the line BRA NxtNewSrc32 ;LOOP BACK FOR MORE endif ;<14> IF 0 THEN ;This is great code but it is only good if the dst left and right ;are both on byte boundaries. bFast0 has can now handle any left ;and right mask with comparable performance. ;****************************************************************************************** ; ; Here's where Andy handles the case of MisAligned copyBits copy mode on a byte boundary. ; ; it's an 8 bit boundary, so handle it. Calculate the address adjustments in D7 from the ; bit offset in D6 and mask in D1. First decode the mask, casing out on the direction ; in A0 bFastMisaligned MOVE.L D1,D3 ;get mask MOVEQ #0,D1 ;assume minimum MOVE.W D6,D0 ASR #3,D0 ;turn into byte number MOVE.W A0,D5 ;remember direction BPL.S @0 ;if positive, we're cool NOT.L D3 ;invert the mask for other direction @0 TST.L D3 BMI.S Got1stOffset ;if on, we're done ADDQ #1,D1 LSL.L #8,D3 BMI.S Got1stOffset ;if on, we're done ADDQ #1,D1 LSL.L #8,D3 BMI.S Got1stOffset ;if on, we're done ADDQ #1,D1 ; we got the mask offset in D1 and the byte offset in D0, so compute the bump factors Got1stOffset ADD.W D1,D0 ;compute byte offset MOVE.W D0,D7 ;remember offset SWAP D7 MOVE.W D1,D7 ;use mask offset for dest MOVE.W D5,D0 ;remember bump direction move.w destPixCnt(a6),d5 ;get pixel count ext.l d5 move.w dstShift(a6),d1 ;get shift count lsl.l d1,d5 ;convert pixels to bits lsr.l #3,d5 ;convert bits to bytes TST.W D0 ;test direction BMI BlockMoveRight ;if right, go there and do it BRA.S SL1Loop ;go to top of loop ;---------------------------------------------------------------------------- ; done with this scan line, so bump to the next scan line and loop until done SL1Done RTS ;go Home SL1Next SUB.W D7,A4 ;undo source offset SWAP D7 SUB.W D7,A5 ;undo dest offset MOVEQ #0,D0 MOVE.W LONGCNT(A6),D0 ;get long count ADDQ #1,D0 ASL #2,D0 ;turn into byte count ADD.L D0,A4 ADD.L D0,A5 ADD.W SRCBUMP(A6),A4 ;bump source ; ADD.W A3,A5 ;bump destination SUBQ.W #1,HEIGHT(A6) ;decrement scan line count BEQ.S SL1Done ;if no more, go home ; here's the top of the outer loop where we adjust the addresses by the offsets in D7 SL1Loop ADD.W D7,A5 SWAP D7 ADD.W D7,A4 ; get the byte count and blast the scan line SL1Blast MOVE.L D5,D0 MOVE.L A4,A0 MOVE.L A5,A1 ; Special BlockMove subroutine optimized for this situation. The source is in A0 ; and dest in A1, with byte count in D0. Note things are already pre-bumped for ; the MoveRight case. Note that we assume that no move is bigger than 32KBytes, ; to save a little speed (no scanline is that big!) BlockMoveLeft ; for small moves, all this casing out is a losing battle, so dive in quickly CMP.W #32,D0 ;is it really small? BLT.S FinishUpLeft ;if so, finish up last few ; make sure the destination is always longword aligned by moving up to 3 bytes MOVE.W A1,D1 ;get destination AND.W #3,D1 ;low two bits only BEQ.S MediumLeft ;if 0, skip JMP LeftAlign(D1.W*4) LeftAlign NOP NOP MOVE.B (A0)+,(A1)+ SUBQ #1,D0 MOVE.B (A0)+,(A1)+ SUBQ #1,D0 MOVE.B (A0)+,(A1)+ SUBQ #1,D0 ; we've got a medium-sized block to move (at least 32), so handle it with an unwound MOVE.L loop MediumLeft MOVE.W D0,D1 LSR.W #5,D1 ;divide by 32 BRA.S @2 @1 MOVE.L (A0)+,(A1)+ ;move 32 bytes MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ @2 DBRA D1,@1 ;move it ; now we have 31 or less bytes left to move AND #31,D0 FinishUpLeft MOVE.W LOffsetTable(D0.W*2),D0 JMP LastLeft(D0) LastLeft Left1F MOVE.L (A0)+,(A1)+ Left1B MOVE.L (A0)+,(A1)+ Left17 MOVE.L (A0)+,(A1)+ Left13 MOVE.L (A0)+,(A1)+ LeftF MOVE.L (A0)+,(A1)+ ;move next 32 (64 total) LeftB MOVE.L (A0)+,(A1)+ Left7 MOVE.L (A0)+,(A1)+ Left3 MOVE.W (A0)+,(A1)+ Left1 MOVE.B (A0)+,(A1)+ Left0 DoneBlockMove BRA.s SL1Next Left1E MOVE.L (A0)+,(A1)+ Left1A MOVE.L (A0)+,(A1)+ Left16 MOVE.L (A0)+,(A1)+ Left12 MOVE.L (A0)+,(A1)+ LeftE MOVE.L (A0)+,(A1)+ LeftA MOVE.L (A0)+,(A1)+ Left6 MOVE.L (A0)+,(A1)+ Left2 MOVE.W (A0)+,(A1)+ BRA.s SL1Next Left1C MOVE.L (A0)+,(A1)+ Left18 MOVE.L (A0)+,(A1)+ Left14 MOVE.L (A0)+,(A1)+ Left10 MOVE.L (A0)+,(A1)+ LeftC MOVE.L (A0)+,(A1)+ Left8 MOVE.L (A0)+,(A1)+ Left4 MOVE.L (A0)+,(A1)+ BRA.s SL1Next Left1D MOVE.L (A0)+,(A1)+ Left19 MOVE.L (A0)+,(A1)+ Left15 MOVE.L (A0)+,(A1)+ Left11 MOVE.L (A0)+,(A1)+ LeftD MOVE.L (A0)+,(A1)+ Left9 MOVE.L (A0)+,(A1)+ Left5 MOVE.L (A0)+,(A1)+ MOVE.B (A0)+,(A1)+ BRA.s SL1Next LOffsetTable DC.W Left0-LastLeft DC.W Left1-LastLeft DC.W Left2-LastLeft DC.W Left3-LastLeft DC.W Left4-LastLeft DC.W Left5-LastLeft DC.W Left6-LastLeft DC.W Left7-LastLeft DC.W Left8-LastLeft DC.W Left9-LastLeft DC.W LeftA-LastLeft DC.W LeftB-LastLeft DC.W LeftC-LastLeft DC.W LeftD-LastLeft DC.W LeftE-LastLeft DC.W LeftF-LastLeft DC.W Left10-LastLeft DC.W Left11-LastLeft DC.W Left12-LastLeft DC.W Left13-LastLeft DC.W Left14-LastLeft DC.W Left15-LastLeft DC.W Left16-LastLeft DC.W Left17-LastLeft DC.W Left18-LastLeft DC.W Left19-LastLeft DC.W Left1A-LastLeft DC.W Left1B-LastLeft DC.W Left1C-LastLeft DC.W Left1D-LastLeft DC.W Left1E-LastLeft DC.W Left1F-LastLeft ;---------------------------------------------------------------------------- ; done with this scan line, so bump to the next scan line and loop until done SR1Done RTS SR1Next SUB.W D7,A4 ;undo source offset SWAP D7 SUB.W D7,A5 ;undo dest offset MOVEQ #0,D0 MOVE.W LONGCNT(A6),D0 ;get long count ADDQ #1,D0 ASL #2,D0 ;turn into byte count NEG.L D0 ;negate it ADD.L D0,A4 ADD.L D0,A5 ADD.W SRCBUMP(A6),A4 ;bump source ; ADD.W A3,A5 ;bump destination SUBQ.W #1,HEIGHT(A6) ;decrement scan line count BEQ.S SR1Done ;if no more, then go home ; here's the top of the outer loop where we adjust the addresses by the offsets in D7 BlockMoveRight ADD.W D7,A5 SWAP D7 ADD.W D7,A4 ; get the byte count and blast the scan line SR1Blast MOVE.L D5,D0 ;byte count stored in d5 MOVE.L A4,A0 MOVE.L A5,A1 ; Handle the case of moving to the right MoveRight CMP.W #32,D0 ;is it really small? BLT.S FinishUpRight ;if so, finish up last few ; make sure the destination is always longword aligned by moving up to 3 bytes MOVE.W A1,D1 ;get destination AND.W #3,D1 ;low two bits only EOR.W #3,D1 ;flip sense JMP RightAlign(D1.W*4) RightAlign MOVE.B -(A0),-(A1) SUBQ #1,D0 MOVE.B -(A0),-(A1) SUBQ #1,D0 MOVE.B -(A0),-(A1) SUBQ #1,D0 ; we've got a medium-sized block to move (at least 32), so handle it with an unwound MOVE.L loop MediumRight MOVE.W D0,D1 LSR.W #5,D1 ;divide by 32 BRA.S @2 @1 MOVE.L -(A0),-(A1) ;move 32 bytes MOVE.L -(A0),-(A1) MOVE.L -(A0),-(A1) MOVE.L -(A0),-(A1) MOVE.L -(A0),-(A1) MOVE.L -(A0),-(A1) MOVE.L -(A0),-(A1) MOVE.L -(A0),-(A1) @2 DBRA D1,@1 ;move the bulk of it ; now we have 31 or less bytes left to move AND #31,D0 FinishUpRight MOVE.W ROffsetTable(D0.W*2),D0 ;+++ JMP LastRight(D0) JMP (QGLastRight,PC,D0) ; this is a hack - this JMP must be immediately before the table QGLastRight Right1F MOVE.L -(A0),-(A1) Right1B MOVE.L -(A0),-(A1) Right17 MOVE.L -(A0),-(A1) Right13 MOVE.L -(A0),-(A1) RightF MOVE.L -(A0),-(A1) ;move next 32 (64 total) RightB MOVE.L -(A0),-(A1) Right7 MOVE.L -(A0),-(A1) Right3 MOVE.W -(A0),-(A1) Right1 MOVE.B -(A0),-(A1) Right0 BRA.s SR1Next Right1E MOVE.L -(A0),-(A1) Right1A MOVE.L -(A0),-(A1) Right16 MOVE.L -(A0),-(A1) Right12 MOVE.L -(A0),-(A1) RightE MOVE.L -(A0),-(A1) RightA MOVE.L -(A0),-(A1) Right6 MOVE.L -(A0),-(A1) Right2 MOVE.W -(A0),-(A1) BRA.s SR1Next Right1C MOVE.L -(A0),-(A1) Right18 MOVE.L -(A0),-(A1) Right14 MOVE.L -(A0),-(A1) Right10 MOVE.L -(A0),-(A1) RightC MOVE.L -(A0),-(A1) Right8 MOVE.L -(A0),-(A1) Right4 MOVE.L -(A0),-(A1) BRA.s SR1Next Right1D MOVE.L -(A0),-(A1) Right19 MOVE.L -(A0),-(A1) Right15 MOVE.L -(A0),-(A1) Right11 MOVE.L -(A0),-(A1) RightD MOVE.L -(A0),-(A1) Right9 MOVE.L -(A0),-(A1) Right5 MOVE.L -(A0),-(A1) MOVE.B -(A0),-(A1) BRA.s SR1Next ROffsetTable DC.W Right0-QGLastRight DC.W Right1-QGLastRight DC.W Right2-QGLastRight DC.W Right3-QGLastRight DC.W Right4-QGLastRight DC.W Right5-QGLastRight DC.W Right6-QGLastRight DC.W Right7-QGLastRight DC.W Right8-QGLastRight DC.W Right9-QGLastRight DC.W RightA-QGLastRight DC.W RightB-QGLastRight DC.W RightC-QGLastRight DC.W RightD-QGLastRight DC.W RightE-QGLastRight DC.W RightF-QGLastRight DC.W Right10-QGLastRight DC.W Right11-QGLastRight DC.W Right12-QGLastRight DC.W Right13-QGLastRight DC.W Right14-QGLastRight DC.W Right15-QGLastRight DC.W Right16-QGLastRight DC.W Right17-QGLastRight DC.W Right18-QGLastRight DC.W Right19-QGLastRight DC.W Right1A-QGLastRight DC.W Right1B-QGLastRight DC.W Right1C-QGLastRight DC.W Right1D-QGLastRight DC.W Right1E-QGLastRight DC.W Right1F-QGLastRight ENDIF DC.B '(c) Apple Computer Inc., 1983-1989' ENDPROC