mac-rom/QuickDraw/BitBlt.a

4943 lines
158 KiB
Plaintext
Raw Normal View History

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