sys7.1-doc-wip/QuickDraw/RgnBlt.a

4243 lines
132 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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