mac-rom/QuickDraw/QDUtil.a

4742 lines
144 KiB
Plaintext

;
; File: QDUtil.a
;
; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved.
;
; This file is used in these builds: Mac32 BigBang
;
;
; Change History (most recent first):
;
; <SM7> 9/12/93 joe seperately conditionalize out ElsieTranslate24To32.
; <SM6> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
; so they can conditionalized out of the build.
; <SM5> 1/26/93 kc Fix bug in GetAlphaMask. (renamed mask to alphaMask to avoid
; name collision)
; <SM4> 1/25/93 kc Roll in Shannon Holland's alpha channel stuff.
; <SM3> 7/16/92 CSS Update from Reality:
; <R21> 6/8/92 SAH #1031825: Changed ColorMap to ignore the multColor flag.
; <SM2> 6/11/92 stb <sm 6/9/92>stb Synch with QDciPatch.a; added comments to
; ColorMap, AlphaDispatch, GetPixel, GetCPixel, FillClipScanLine,
; FillClipOrLine, FAST11, FillClipXLine.
; <20> 11/26/90 SMC Fixed slab pattern hiliting. With BAL.
; <19> 11/6/90 SMC Fixed NOPfgColorTable range problem in Mac32 build. With KON.
; <18> 11/5/90 SMC Fixed FastTab range problem in Mac32 build. With KON.
; <17> 10/31/90 SMC Fixed alpha channel bugs with BAL.
; <16> 10/17/90 SMC Fixed pattern alignment problem in FillClipXLine. With KON.
; <15> 10/17/90 SMC Changed speedup method used in <13> to work in cases where
; someone has put a semi-legal value in fgcolor or bkcolor, such
; as -1 instead of 1. With BAL.
; <14> 10/17/90 KON The default colors in ColorMap should be inverted if Multcolor
; is set and destination is direct. With SMC.
; <13> 10/1/90 KON Speedup to 1-bit fg/bg pixel replication. With BAL.
; <12> 9/27/90 SMC Fixed pattern hilite setup in SlabMode for 16 and 32-bit.
; Slabbed pattern hilite still has problems but now it has one
; less.
; <11> 9/18/90 SMC Fixed GetCPixel to return valid color at points along top and
; left edges of gdevice.
; <10> 9/18/90 BG Removed <6>, <8>. 040s are behaving more reliably now.
; <9> 8/16/90 dba fix up the implementation of VisRgnChanged
; <8> 7/20/90 BG Added some more EclipseNOPs for flakey 040s.
; <7> 7/20/90 gbm Change comment to reflect new reality
; <6> 6/27/90 BG Added NOPs for flakey 040s.
; <5> 6/21/90 KON Fix getPixel and getCPixel so they work with pixmap with
; pmVersion=4 (needs 32-bit addressing).
; <4> 6/4/90 KON Hack to make 1-bit old port copy mode work.
; <3> 3/26/90 KON Add VisRgnChanged call (trap $A0A5).
; <2> 2/28/90 JJ Added the routine ElsieTranslate24To32, a new address
; translation routine appropriate for the VISA decoder.
; <1.8> 11/18/89 BAL Added in QuickerDraw loops for copy mode and 8-bit arithmetic
; DrawSlab
; <¥1.7> 7/14/89 BAL For Aurora: Final CQD
; <1.6> 6/30/89 BAL Init FG = black and BK = white flags in ColorMap¶
; <1.5> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
; file (colorequ.a), got rid of QuickDraw nFiles dependencies and
; fixed up necessary filesÉ
; <¥1.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
; 1/22/89 BAL Altered DrawSlab loops to use patVPos as a long.
; 9/19/88 BAL Altered ColorMap, DrawSlab to use common stack frame file
; 'Drawing Vars.a'
; 9/15/88 BAL Compute slab bit-width as a long
; 5/6/88 BAL Rolled in fix to set bcolor to white during transparent blit
; 5/6/88 BAL Altered ColorMap to clean invColor and colorTable ptrs
; 5/4/88 BAL Modified XorSlab to maintain bit width as a long
; 4/14/88 BAL Modified GetCPixel to operate in 32 bit addressing mode
; 1/21/87 EHB Modified colorMap to check grafPort type before using colors
; 1/3/87 CRC color correction in colorMap; bug fixes in arithmetic modes
; 12/30/86 EHB Modified colorMap to check grafPort type before using colors
; 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 In PatExpand, only colorize pattern if copy mode Added color to
; pattern OR and pattern BIC transfer modes in DrawSlab
; 7/7/86 EHB In ColorMap, use portBits+rowBytes (not rowBytes) (oops!)
; 7/2/86 EHB In ColorMap, use bit 13 of rowbytes to draw old-style colors
; into new-style ports.
; 6/22/86 EHB Added multi-depth patexpand (version 0.1)
; 6/20/86 EHB Added compatibility color mapping to COLORMAP
; 6/17/86 EHB Tweaked GetPixel to work with cGrafPorts
; 6/10/86 EHB Redid DrawSlab to use longwords and 020 instructions.
; 6/9/86 EHB Removed long mask routines in lieu of macros (found a better
; way)
; 6/8/86 EHB Redid XORSlab using 020 instructions
; 6/6/86 EHB Added routines LLeftMask,LRightMask,LBitMask
; 4/16/86 EHB Added 0 byte at end of file for alignment
;
BLANKS ON
STRING ASIS
MACHINE MC68020
;-------------------------------------------------------------
;
; --> UTIL.TEXT
;
; SMALL UTILITY ROUTINES USED BY QuickDraw
;
; MODIFICATIONS
; 16Apr86 EHB Added 0 byte at end of file for alignment
; 6Jun86 EHB Added routines LLeftMask,LRightMask,LBitMask
; 8Jun86 EHB Redid XORSlab using 020 instructions
; 9Jun86 EHB Removed long mask routines in lieu of macros (found a better way)
; 10Jun86 EHB Redid DrawSlab to use longwords and 020 instructions.
; 17Jun86 EHB Tweaked GetPixel to work with cGrafPorts
; 20Jun86 EHB Added compatibility color mapping to COLORMAP
; 22Jun86 EHB Added multi-depth patexpand (version 0.1)
; 2Jul86 EHB In ColorMap, use bit 13 of rowbytes to draw old-style colors
; into new-style ports.
; 7Jul86 EHB In ColorMap, use portBits+rowBytes (not rowBytes) (oops!)
; 22Jul86 EHB In PatExpand, only colorize pattern if copy mode
; Added color to pattern OR and pattern BIC transfer modes in DrawSlab
; 26Jul86 EHB Added support for expanded patterns
; 29Jul86 EHB Use new stack-based EXPAT buffer
; 12Dec86 CRC Added arithmetic modes
; 30Dec86 EHB Modified colorMap to check grafPort type before using colors
; 3Jan87 CRC color correction in colorMap; bug fixes in arithmetic modes
; 21Jan87 EHB Modified colorMap to check grafPort type before using colors
; 14Apr88 BAL Modified GetCPixel to operate in 32 bit addressing mode
; 04May88 BAL Modified XorSlab to maintain bit width as a long
; 06May88 BAL Altered ColorMap to clean invColor and colorTable ptrs
; 06May88 BAL Rolled in fix to set bcolor to white during transparent blit
; 15Sep88 BAL Compute slab bit-width as a long
; 19Sep88 BAL Altered ColorMap, DrawSlab to use common stack frame file 'Drawing Vars.a'
; 22Jan89 BAL Altered DrawSlab loops to use patVPos as a long.
; ; <SM4>.start
; Macros to set the alpha channel mask.
; These will be moved into an interface file as soon as
; the High Level API for manipulating the alpha channel is complete.
;
MACRO
_GetForeAlphaMask
MOVE.W #$0F,d0
JSR ([$E00+$3C0*4])
ENDM
MACRO
_GetBackAlphaMask
MOVE.W #$10,d0
JSR ([$E00+$3C0*4])
ENDM ; <SM4>.end
VisRgnChanged PROC EXPORT ;<26MAR90 KON>
;-----------------------------------------------------------
;
; Procedure VisRgnChanged(thePort: GrafPort);
;
; This call will be needed for video windows so the mask plane
; for touchstone can be updated. Non-video QD simply returns.
;
rts
ENDPROC
BitNot FUNC EXPORT
;-----------------------------------------------------------
;
; Function BitNot(long: LongInt): LongInt;
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
NOT.L (SP) ;INVERT LONG
MOVE.L (SP)+,(SP) ;STORE INTO RESULT
JMP (A0) ;AND RETURN
BitAnd FUNC EXPORT
EXPORT BitXor,BitOr,BitShift
;-----------------------------------------------------------
;
; Function BitAnd(long1,long2: LongInt): LongInt;
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;GET ONE LONG
AND.L (SP)+,D0 ;AND IT WITH THE OTHER
BRA.S DONE ;AND STORE RESULT
;-----------------------------------------------------------
;
; Function BitXor(long1,long2: LongInt): LongInt;
;
BitXor MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;GET ONE LONG
MOVE.L (SP)+,D1 ;GET THE SECOND
EOR.L D1,D0 ;XOR BOTH
BRA.S DONE ;AND STORE RESULT
;-----------------------------------------------------------
;
; Function BitOr(long1,long2: LongInt): LongInt;
;
BitOr MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;GET ONE LONG
OR.L (SP)+,D0 ;OR IT WITH THE OTHER
BRA.S DONE ;AND STORE RESULT
;-----------------------------------------------------------
;
; Function BitShift(long: LongInt; count: INTEGER): LongInt;
;
; positive count --> shift left.
; negative count --> shift right.
;
BitShift MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE (SP)+,D1 ;GET COUNT
BPL.S SHLEFT ;SHIFT LEFT IF POSITIVE
NEG D1 ;MAKE COUNT POSITIVE
MOVE.L (SP)+,D0 ;GET LONG
LSR.L D1,D0 ;SHIFT IT RIGHT
BRA.S DONE ;AND STORE RESULT
SHLEFT MOVE.L (SP)+,D0 ;GET LONG
LSL.L D1,D0 ;SHIFT IT LEFT
DONE MOVE.L D0,(SP) ;STORE THE RESULT
JMP (A0) ;AND RETURN
BitTst FUNC EXPORT
EXPORT BitSet,BitClr
;---------------------------------------------------------
;
; FUNCTION BitTst(bytePtr: Ptr; bitNum: LongInt): BOOLEAN;
;
BSR.S SHARE
MOVE.L (SP)+,A1 ;GET PTR
BTST D0,0(A1,D1.L) ;TEST THE BIT
SNE (SP) ;SET OR CLEAR RESULT
NEG.B (SP) ;CONVERT -1 TO 1
JMP (A0) ;RETURN
;---------------------------------------------------------
;
; PROCEDURE BitSet(bytePtr: Ptr; bitNum: LongInt);
;
BitSet BSR.S SHARE
MOVE.L (SP)+,A1 ;GET PTR
BSET D0,0(A1,D1.L) ;SET THE BIT
; needed for flakey 040s <6>
JMP (A0)
;---------------------------------------------------------
;
; PROCEDURE BitClr(bytePtr: Ptr; bitNum: LongInt);
;
BitClr BSR.S SHARE
MOVE.L (SP)+,A1 ;GET PTR
BCLR D0,0(A1,D1.L) ;SET THE BIT
JMP (A0)
;
;
;
SHARE MOVE.L (A7)+,A1
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D1 ;GET BITNUM
MOVE D1,D0 ;COPY IT
ASR.L #3,D1 ;CONVERT BITS TO BYTES
NOT D0 ;REVERSE BIT SENSE
JMP (A1)
Random FUNC EXPORT
;--------------------------------------------------------------
;
; FUNCTION Random: INTEGER;
;
; returns a signed 16 bit number, and updates unsigned 32 bit randSeed.
;
; recursion is randSeed := (randSeed * 16807) MOD 2147483647.
;
; See paper by Linus Schrage, A More Portable Fortran Random Number Generator
; ACM Trans Math Software Vol 5, No. 2, June 1979, Pages 132-138.
;
; Clobbers D0-D2, A0
;
;
; GET LO 16 BITS OF SEED AND FORM LO PRODUCT
; xalo := A * LoWord(seed)
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE #16807,D0 ;GET A = 7^5
MOVE D0,D2 ;GET A = 7^5
MULU RANDSEED+2(A0),D0 ;CALC LO PRODUCT = XALO
;
; FORM 31 HIGHEST BITS OF LO PRODUCT
; fhi:=HiWord(seed) * ORD4(a) + HiWord(xalo);
;
MOVE.L D0,D1 ;COPY xalo
CLR.W D1
SWAP D1 ;GET HiWord(xalo) as a long
MULU RANDSEED(A0),D2 ;MULT BY HiWord(seed)
ADD.L D1,D2 ;ADD LEFTLO = FHI
;
; GET OVERFLOW PAST 31ST BIT OF FULL PRODUCT
; k:=fhi DIV 32768;
;
MOVE.L D2,D1 ;COPY FHI
ADD.L D1,D1 ;CALC 2 TIMES FHI
CLR.W D1
SWAP D1 ;CALC FHI SHIFTED RIGHT 15 FOR K
;
; ASSEMBLE ALL THE PARTS AND PRE-SUBTRACT P
; seed:=((BitAnd(XALO,$0000FFFF) - P) + BitAnd(fhi,$00007FFF) * b16) + K;
;
AND.L #$0000FFFF,D0 ;GET LO WORD XALO
SUB.L #$7FFFFFFF,D0 ;SUBTRACT P = 2^31-1
AND.L #$00007FFF,D2 ;BitAnd(fhi,$00007FFF)
SWAP D2 ;TIMES 64K
ADD.L D1,D2 ;PLUS K
ADD.L D2,D0 ;CALC TOTAL
;
; IF seed < 0 THEN seed:=seed+p;
;
BPL.S UPDATE
ADD.L #$7FFFFFFF,D0
UPDATE MOVE.L D0,RANDSEED(A0) ;UPDATE SEED
CMP.W #$8000,D0 ;IS NUMBER -32768 ?
BNE.S NUMOK ;NO, CONTINUE
CLR D0 ;YES, RETURN ZERO INSTEAD
NUMOK MOVE.W D0,4(SP) ;RETURN LO WORD AS RESULT
RTS
ForeColor PROC EXPORT
EXPORT BackColor,PortLong,ColorBit,PortWord
;--------------------------------------------------------------
;
; PROCEDURE ForeColor(color: LongInt);
;
MOVEQ #FGCOLOR,D0 ;GET OFFSET TO FGCOLOR
CSHARE MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
TST PORTBITS+ROWBYTES(A0) ;OLD OR NEW PORT?
BPL.S PORTLONG ;=>OLD PORT, INSTALL LONG INTO PORT
MOVE D0,-(SP) ;SAVE OFFSET TO COLOR FIELD
MOVE.L 6(SP),D0 ;GET COLOR (xxxC MYBr gbwb)
MOVE.L PORTBITS+BASEADDR(A0),A0 ;GET HANDLE TO PORT PIXMAP
MOVE.L (A0),A0 ;POINT TO PIXMAP
; CONVERT THE PLANAR BITS (xxxC MYBr gbwb) TO AN RGB VALUE
LSR.L #1,D0 ;CHECK FOR WHITE (->CMYB rgbw)
BCS.S @0 ;=>NOT WHITE
OR #$00E0,D0 ;ELSE SET WHITE BITS (CMY = 111)
@0 LSR #5,D0 ;SHIFT CMYÊINTO LOW NIBBLE
AND #$7,D0 ;CLEAR ALL BUT LOW NIBBLE
MOVE.L QDCOLORS,A0 ;POINT TO DEFAULT COLORS
; SET THE SPECIFIED COLOR
PEA 2(A0,D0*8) ;PUSH ADDRESS OF RGB
CMP #FGCOLOR,4(SP) ;ARE WE SETTING THE FORECOLOR?
BNE.S DOBACK ;=> NO, SET BACKCOLOR
_RGBFORECOLOR ;SET THE FOREGROUND COLOR
BRA.S DONE ;=>AND RETURN
DOBACK _RGBBACKCOLOR ;ELSE SET THE BACKGROUND COLOR
DONE MOVE (SP)+,D0 ;POP THE OFFSET
MOVE.L (SP)+,A1 ;GET THE RETURN ADDRESS
ADDQ #4,SP ;STRIP THE PARAMETER
JMP (A1) ;AND RETURN
;--------------------------------------------------------------
;
; PROCEDURE BackColor(color: LongInt);
;
BackColor
MOVEQ #BKCOLOR,D0 ;GET OFFSET TO BKCOLOR
BRA.S CSHARE ;INSTALL COLOR INTO PORT
;-------------------------------------------------------
;
; PROCEDURE PortLong(long: LongInt);
; INSTALL A LONG INTO CURRENT GRAFPORT. ENTER WITH OFFSET IN D0
;
PortLong
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.L (SP)+,0(A0,D0) ;INSTALL LONG INTO THEPORT
JMP (A1) ;AND RETURN
;--------------------------------------------------------------
;
; PROCEDURE ColorBit(whichBit: INTEGER);
;
ColorBit
MOVEQ #COLRBIT,D0 ;GET OFFSET TO COLRBIT
;FALL THRU INTO PORTWORD
;-------------------------------------------------------
;
; PROCEDURE PortWord(word: INTEGER);
; INSTALL A WORD INTO CURRENT GRAFPORT. ENTER WITH OFFSET IN D0
;
PortWord
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.W (SP)+,0(A0,D0) ;INSTALL WORD INTO THEPORT
JMP (A1) ;AND RETURN
GetMaskTab PROC EXPORT
EXPORT LeftMask,RightMask,BitMask,MaskTab
;----------------------------------------------------------
;
; ASSEMBLY LANGUAGE CALLABLE PROCEDURES LEFTMASK, RIGHTMASK, AND BITMASK:
;
; ENTER WITH COORDINATE IN D0, RETURNS WITH 16 BIT MASK IN D0
; NO OTHER REGISTERS ALTERED.
;
LEA MaskTab,A0 ;POINT TO MASK TABLE
RTS ;AND RETURN
LeftMask
AND #$F,D0 ;TREAT MOD 16
ADD D0,D0 ;DOUBLE FOR TABLE
MOVE MASKTAB+32(D0),D0 ;GET LEFTMASK
RTS
RIGHTMASK
AND #$F,D0 ;TREAT MOD 16
ADD D0,D0 ;DOUBLE FOR TABLE
MOVE MASKTAB(D0),D0 ;GET RIGHT MASK
RTS
BITMASK AND #$F,D0 ;TREAT MOD 16
ADD D0,D0 ;DOUBLE FOR TABLE
MOVE MASKTAB+64(D0),D0 ;GET BITMASK
RTS
MASKTAB DC.W $0000,$8000,$C000,$E000 ;TABLE OF 16 RIGHT MASKS
DC.W $F000,$F800,$FC00,$FE00
DC.W $FF00,$FF80,$FFC0,$FFE0
DC.W $FFF0,$FFF8,$FFFC,$FFFE
DC.W $FFFF,$7FFF,$3FFF,$1FFF ;TABLE OF 16 LEFT MASKS
DC.W $0FFF,$07FF,$03FF,$01FF
DC.W $00FF,$007F,$003F,$001F
DC.W $000F,$0007,$0003,$0001
DC.W $8000,$4000,$2000,$1000 ;TABLE OF 16 BIT MASKS
DC.W $0800,$0400,$0200,$0100
DC.W $0080,$0040,$0020,$0010
DC.W $0008,$0004,$0002,$0001
; translation for arithmetic modes when drawn at 1 bit per pixel
arithMode PROC EXPORT
; hilite
;avg addPin addOver subPin trans max subOver min
DC.B srcCopy, srcBic, srcXor, srcOr, srcOr, srcBic, srcXor, srcOr
ColorMap PROC EXPORT
IMPORT arithMode
IMPORT NOPfgColorTable
;Êrolled in from QDciPatchROM.a <sm 6/9/92>stb
;----------------------------------------------------------------
;
; PROCEDURE ColorMap: (pat: Pattern; mode: INTEGER);
;
; ADJUST INPUT MODE AND PATTERN TO ACCOMPLISH COLOR SEPARATION.
; POTENTIALLY MODIFIES: LOCMODE, NEWPATTERN, LOCPAT, FCOLOR, BCOLOR.
;
; ADJUSTED MODE IS RETURNED IN LOCMODE(A6).
; IF PATTERN IS ADJUSTED, THEN NEWPATTERN(A6) IS SET FALSE AND LOCPAT(A6) IS MODIFIED.
; FCOLOR(A6) AND BCOLOR(A6) ARE MODIFIED AS DESCRIBED BELOW.
;
; IF OLD PORT, TRANSLATES OLD-STYLE FGCOLOR, BKCOLOR INTO AN RGB,
; AND THEN GETS THE INDEX FOR THAT COLOR. FOR ALL PORTS, THE
; RETURNED COLOR CONTAINS THE PIXEL REPLICATED THROUGHOUT THE LONG
; (SUITABLE FOR MASKING).
;
; FOR EITHER MODE, IF THE DESTINATION IS ONE BIT DEEP, DO PLANAR REMAPPING
; SO THAT FASTEST COPYBITS BLT ROUTINES DON'T NEED TO APPLY COLOR.
;
; CLOBBERS A0-A1,D0-D2
;
; CALLED BY: DRAWARC, DRAWLINE, STRETCH
; A6 STACK FRAME ALLOCATED BY CALLER, USED LOCALLY.
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;
&CurFile SETC 'COLORMAP'
INCLUDE 'DrawingVars.a'
;-------------------------------------------------
PARAMSIZE EQU 0 ;SIZE OF PARAMETERS
VARSIZE EQU 0 ;SIZE OF LOCALS
; LINK A4,#VARSIZE ;MAKE A STACK FRAME
MOVEM.L D3-D7/A2-A3,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A2 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A2),A2 ;POINT TO THE PORT
MOVE locMode(A6),D3 ;get the mode
MOVE.L FGCOLOR(A2),D6 ;GET FOREGROUND COLOR INTO D6
MOVE.L BKCOLOR(A2),D7 ;GET BACKGROUND COLOR INTO D7
; <1.6> BAL
@modeOK MOVE D3,D1 ;make a copy of the mode
AND #$FFF7,D3 ;clear the pattern bit
EOR D3,D1 ;set only the pattern bit
CMP #srcXor,D3 ;could it be replaced by hilite?
BNE.S @noXorSub
BSET #hiliteBit,HiliteMode ;check to see if highlight bit was set
BNE.S @noXorSub ;if not, invert old way
MOVE #$32,D3 ;set to src highlight
@noXorSub
BTST #5,D3 ;an arithmetic mode?
BEQ.S @leaveModeAlone ;skip if no mode
CMP #1,dstPix+pixelSize(A6) ;1 bit per pixel on the destination
BNE.S @leaveModeAlone
AND #$07,D3 ;get variants
MOVE.B arithMode(D3),D3 ;get mapped mode in 1 bit
@leaveModeAlone
OR D1,D3 ;combine mapped mode and pattern bit
MOVE D3,locMode(A6) ;save off altered mode
; <17> Beginning of alpha channel changes
CLR.B alphaMode(A6) ;clear the alpha mode to default
BTST #5,D3 ;check again for arithmetic modes
BNE @noalpha ;skip alpha stuff if arithmetic
MOVE.W dstShift(A6),D0 ;yes, get pixel size
; MOVE.L ((NOPfgColorTable-*).L,PC,D0.W*4),D0
LEA (NOPfgColorTable-*).L,A1 ;get distance from here to NOPfgColorTable
LEA *-6(A1.L),A1 ;get address of "white" table
MOVE.L 0(A1,D0.W*4),D0 ;get default mask for current depth
MOVE.L D0,alphaBack(A6) ;save for later use
MOVE.W D3,D5 ;make copy of adjusted mode
AND.W #$03,D5 ;mask off all but base mode
CMP.W #srcXor,D5 ;are we xoring?
BEQ.S @1 ;yes, use normal default mask
MOVEQ #-1,D0 ;get all ones
@1: MOVE.L D0,alphaMask(A6) ;save default alphaMask
TST portBits+rowBytes(A2) ;is it an old port?
BPL @noalpha ;yes, alpha mode is illegal
MOVE.W dstPix+pixelSize(A6),D0 ;get depth of destination
CMP.W #16,D0 ;direct device?
BLT @noalpha ;no, skip this stuff ; <SM4>
MOVE.L grafVars(A2),D4 ;get grafvars handle
BEQ @noalpha ;no grafvars, no alpha
MOVE.L D4,A0 ;copy handle
MOVE.L (A0),A1 ;dereference handle
BTST #PmNewGVBit-8,pmFlags(A1) ;make sure grafvars have been expanded
BEQ.S @noalpha ;if not, bail
MOVE.B streamMode(A1),alphaMode(A6);save alpha mode in stack frame
SUB #18,SP ;make room on stack for results and first error ; <SM4>.start
move.l a0,-(sp) ;push GrafVars handle
PEA 14(SP) ;push pointer to where we want results for background stream
subq #2,sp ;room for error
move.l a0,-(sp) ;push GrafVars handle
PEA 16(SP) ;push pointer to where we want results for foreground stream
_GetForeAlphaMask ;get foreground stream and ratio
addq #2,sp ;clear error
_GetBackAlphaMask ;get background stream and ratio
addq #2,sp ;clear error ; <SM4>.end
MOVE.L (SP)+,D0 ;get alpha mask
MOVE.L (SP)+,D4 ;get alpha fore color
CMP.W #srcXor,D5 ;are we xoring?
BNE.S @2 ;no, use normal default mask
MOVE.L D4,D0 ;yes, use alpha fore color as alpha mask
@2: MOVE.L D0,alphaFore(A6) ;save alpha mask
ADDQ #4,SP ;throw away background mask
MOVE.L (SP)+,D5 ;get alpha back color
MOVEQ #0,D2 ;clear out alpha mask
MOVE.B alphaMode(A6),D0 ;get alpha again
BNE.S @3 ;if non-zero, use that value
MOVEQ #3,D0 ;if zero, draw to both
@3: BTST #1,D0 ;are we drawing to graphics?
BEQ.S @4 ;no, skip
OR.L alphaFore(A6),D2 ;yes, add alpha bits to mask
OR.L D4,D6 ;apply alphaFgColor to the foreground color
OR.L D5,D7 ;apply alphaBkColor to the background color
@4: BTST #0,D0 ;is the alpha going to be drawn?
BEQ.S @5 ;no, then don't apply alpha to fg,bk colors
OR.L alphaBack(A6),D2 ;yes, add graphic bits to mask
@5: MOVE.L D2,alphaMask(A6) ;save alpha mask in stack frame
NOT.L D2 ;check for mask of all ones
SNE alphaMode(A6) ;if mask of all ones, set alphamode to true
@noalpha
; <17> End of alpha channel changes
MOVE COLRBIT(A2),D2 ;GET COLOR BIT SELECT
MOVEQ #-1,D4 ;DEFAULT VALUE FOR FGLONG
MOVEQ #0,D5 ;DEFAULT VALUE FOR BKLONG
; IF IT IS AN OLD PORT, AND WE ARE GOING TO THE SCREEN, THEN DON'T DO
; SEPARATION, JUST MAP PLANAR COLOR VALUES INTO COLOR INDICES.
; IF IT IS A NEW PORT, DON'T NEED TO REMAP THE VALUES (UNLESS ONE BIT DEEP).
; if pattern mode and new pattern, leave black and white
MOVE D3,D0 ;copy the mode
BCLR #3,D0 ;clear pattern bit
; not necessary since d1 already has pattern bit
; SNE D1 ;remember that the pattern bit was set
; CMP #$32,D0 ;is it hilite? <¥¥¥>
; BEQ COLOROK ;if so, use black/white <¥¥¥>
CMP #srcXor,D0 ;is it srcXor or patXor?
BEQ COLOROK ;if so, use black/white
CMP #notSrcXor,D0 ;is it notSrcXor or notPatXor?
BEQ COLOROK ;if so, use black/white
TST.B D1 ;IS IT A PATTERN MODE?
BEQ.S DestBitMap ;if not skip, otherwise check if its a multibit pattern <08JUNE92 SAH>
ISPAT TST.B NEWPATTERN(A6) ;FLAG TRUE IF DESTINATION IS PIXMAP
BEQ.S DestBitMap ;=>YES, GET COLOR PIXEL MASKS
MOVE.L LOCPAT(A6),A0 ;GET PATTERN POINTER
MOVE.L (A0),A0 ;GET HANDLE TO PATTERN
MOVE.L (A0),A0 ;GET POINTER TO PATTERN
TST PATTYPE(A0) ;WHAT TYPE OF PATTERN IS IT?
BNE COLOROK ;=>A NEW ONE, BLACK FG & WHITE BK
DestBitMap
;here src is either an old pattern or image data
TST PORTBITS+ROWBYTES(A2) ;old port or new?
BPL.S REMAP ;if old, go check color bit
CMP #2,DSTPIX+PIXELSIZE(A6) ;worry about fg remapping?
BGT.S REP ;if 4 or 8 bit, just replicate the pixel
CMP.L D6,D7 ;is the fg color the same as the bk color?
BNE.S REP ;if not, no conflict; just replicate the pixel
; If the source RGBs are identical, donÕt change the foreground. But, if they started out
; different, and they mapped to be the same thing, then flip (invert) the foreground color.
LEA RGBFgColor(A2),A0 ;get the forecolor RGB from the port
LEA RGBBkColor(A2),A1 ;and get the backcolor as well
CMP.L (A0)+,(A1)+ ;if the R or G are not equal, flip the back color
BNE.S @goOnAndFlip
CMP (A0)+,(A1)+ ;if R, G and B are equal, donÕt flip the back color
BEQ.S REP
@goOnAndFlip
tst d2 ;color bit set? <1.6> BAL
bne.s rep ;yes, fg=bk is ok <1.6> BAL
LEA RGBFgColor(A2),A0 ;get the forecolor RGB from the port
SUBQ #6,SP ;make room for the color
MOVE.L SP,A1 ;set up as destination
MOVE.L (A0)+,(A1)+ ;copy R, G to stack
MOVE (A0)+,(A1)+ ;copy B to stack
MOVE.L SP,-(SP) ;push the copy of the forecolor RGB
_InvertColor ;get the furthest thing from it
SUBQ #4,SP ;make room for the function result
PEA 4(SP) ;push the inverted RGB
_Color2Index ;get its index
MOVE.L (SP)+,D6 ;and put it in the forecolor register
ADDQ #6,SP ;throw away the color placeholder
BRA.S REP ;now the foreground, background longs can be made
REMAP TST D2 ;GET COLOR BIT SELECT
BMI COLOROK ;COLRBIT NEG MEANS NO COLOR
BNE.S REMAP2 ;=>DOING PLANES, DO OLD WAY
CMP #1,DSTPIX+PIXELSIZE(A6) ;IS PIXELSIZE 1?
BEQ.S remapOld1bit ;=>yes, REMAP COLORS FOR old 1-bit pixels
MOVE.L D7,D0 ;GET BKCOLOR (xxIC MYBr gbwb)
BSR mapToColor
MOVE.L D0,D7 ;get mapped back color
MOVE.L D6,D0 ;GET FGCOLOR (xxIC MYBr gbwb)
BSR mapToColor
MOVE.L D0,D6 ;get mapped fore color
; REPLICATE THE RETURNED COLOR THROUGHOUT THE LONG
REP MOVE DSTPIX+PIXELSIZE(A6),D0 ;GET THE SIZE OF THE PIXEL
cmp #1,d0
beq.s DoOneBit
MOVE.L D6,D4 ;COPY FG PIXEL
MOVE.L D7,D5 ;COPY BK PIXEL
MOVEQ #32,D1 ;GET SIZE OF A LONG
NXTPXL SUB D0,D1 ;SAY WE'VE DONE A PIXEL
BLE.S COLOROK ;=>IT WAS THE LAST ONE
LSL.L D0,D4 ;PREPARE FOR NEXT FG PIXEL
LSL.L D0,D5 ;PREPARE FOR NEXT BK PIXEL
OR.L D6,D4 ;INSTALL FG PIXEL
OR.L D7,D5 ;INSTALL BK PIXEL
BRA.S NXTPXL ;=>DO ENTIRE LONG
DoOneBit
LSR.L #1,D6 ;if 1-bit, fg and bk end up as 0 or -1
SUBX.L D4,D4 ;note that this ignores whatever is in the other
LSR.L #1,D7 ; 31 bits incase someone (like the standard MBDF)
SUBX.L D5,D5 ; puts -1 instead of 1 in forecolor.
bra.s COLOROK
; From here to COLOROK, the port is old, the destination is 1 bit, the modes are old
remapOld1bit ;Special case colorbit is zero
btst #0,d6
bne.s @fgOK
moveq #0,d4
@fgOK
btst #0,d7
beq.s ColorOK
moveq #-1,d5
bra.s ColorOK
REMAP2 MOVEQ #3,D0 ;MASK FOR BOTTOM 2 BITS
AND D3,D0 ;GET 2 BITS OF MODE
BEQ.S COPY ;BR IF COPY MODE
;
; THE XOR MODES DEPEND ON NEITHER FOREGROUND OR BACKGROUND COLOR
;
CMP #2,D0 ;IS IT SOME KIND OF XOR ?
BEQ.S COLOROK ;YES, THEY DON'T CHANGE
BGT.S BICMODE ;BRANCH IF BIC
;ELSE MUST BE OR
;
; THE OR MODES DEPEND ONLY ON THE FOREGROUND COLOR
;
ORMODE MOVE.L D6,D1 ;GET FOREGROUND COLOR
SHARE BTST D2,D1 ;TEST FOREGROUND COLOR BIT
BNE.S COLOROK ;NO CHANGE IF FG TRUE
EOR #2,D3 ;ELSE INVERT MODE BIT 2
BRA.S NEWMODE ;UPDATE MODE AND QUIT
;
; THE BIC MODES DEPEND ONLY ON THE BACKGROUND COLOR
;
BICMODE MOVE.L D7,D1 ;GET BACKGROUND COLOR
NOT.L D1 ;INVERT IT
BRA SHARE ;AND SHARE CODE
;
; THE COPY MODES DEPEND ON BOTH FOREGOUND AND BACKGROUND
;
COPY MOVE.L D6,D0 ;GET FOREGROUND COLOR
MOVE.L D7,D1 ;GET BACKGROUND COLOR
BTST D2,D0 ;TEST FOREGROUND COLOR BIT
BEQ.S FORE0 ;BRANCH IF IT'S ZERO
FORE1 BTST D2,D1 ;TEST BACKGROUND COLOR BIT
BEQ.S COLOROK ;NO CHANGE IF BKGND FALSE
MOVEQ #8,D3 ;ELSE REPLACE MODE = PAT COPY
USEPAT MOVE.L GRAFGLOBALS(A5),A0 ;GET GLOBAL POINTER
LEA BLACK(A0),A0 ;POINT TO BLACK PATTERN
MOVE.L A0,LOCPAT(A6) ;REPLACE PATTERN WITH BLACK
SF NEWPATTERN(A6) ;AND SET NEWPATTERN FALSE
BRA.S NEWMODE ;UPDATE MODE AND QUIT
FORE0 BTST D2,D1 ;TEST BACKGROUND COLOR BIT
BNE.S INVMODE ;IF BK TRUE, INVERT MODE
MOVEQ #12,D3 ;ELSE REPLACE MODE = NOTPAT COPY
BRA.S USEPAT ;AND PATTERN WITH BLACK
INVMODE EOR #4,D3 ;USE INVERSE OF MODE <HACK>
NEWMODE MOVE D3,LOCMODE(A6) ;CHANGE INPUT MODE
COLOROK MOVE.L D4,FCOLOR(A6) ;RETURN EXTENDED PIXEL
MOVE.L D5,BCOLOR(A6) ;RETURN EXTENDED PIXEL
BTST #5,D3 ;is it an arithmetic mode?
BEQ noArith ;no arithmetic inputs to set up
MOVE DSTPIX+PIXELSIZE(A6),D7 ;GET THE SIZE OF THE PIXEL
MOVE.L bkColor(A2),D5 ;get the background color
TST PORTBITS+ROWBYTES(A2) ;OLD OR NEW GRAFPORT?
BMI.S setOpColor ;new grafPort, use fields in port
; check mode to see if new arithmetic mode in old port
; if so, set up pin and weight to default values
; add with pin default pin is white
; sub with pin default pin is black
; blend default weight is 50% gray
MOVE.L D5,D0 ;pass background color to mapToColor
BSR mapToColor ;turn the old QD bits into a color long
MOVE.L D0,D5 ;save it for later
LEA HiliteRGB,A2 ;get hilite color from low memory
MOVEQ #$07,D0 ;arithmetic mode variants 0 É 7
AND D3,D0 ;get masked mode
SUBQ #1,D0 ;less add with pin variant
BEQ.S @setWhite ;if add with pin, set to white
BMI.S @setGray ;if average, set to gray
LEA xrgbBlack,A0 ;point to black
BRA.S setUpPinWeight
@setWhite
LEA xrgbWhite,A0 ;point to white
BRA.S setUpPinWeight
@setGray
LEA xrgbGray,A0 ;point at gray
BRA.S setUpPinWeight
setOpColor
; set up pin, weight rgbÕs for modes max, min, and avg
; set up weightÕs complement for average
; note that rgb in pin & notWeight are in reverse order from source
MOVE.L ([grafVars,A2]),A0 ;point to weight value
LEA 6(A0),A2 ;point to hilite color
; Set up locals in A6 for arithmetic modes in bltBlt, rgnBlt, drawSlab, stretch
setUpPinWeight
MOVEQ #2,D1 ;do three times
LEA pin+6(A6),A1 ;word past last pin value
LEA notWeight+6(A6),A3 ;word past last not weight value
@nextPin
MOVE (A0)+,D0 ;get red components of pin, weight
BNE.S @notZero ;if input is zero, change it to 1
MOVEQ #1,D0 ;so that complement will be -1 (FFFF)
@notZero
MOVE D0,-(A1) ;save red as is for pin, weight
NEG D0 ;flip for complement of weight
MOVE D0,-(A3) ;save red destination weight
DBRA D1,@nextPin
SUBQ #6,SP ;make room for the color
SUBQ #4,SP ;space for function result
MOVE.L A2,-(SP) ;pass pointer to hilite color
_Color2Index ;leave pixel on stack (hilite color)
CMP.L (SP),D5 ;same as the background?
BNE.S @notSame
LEA 4(SP),A1
MOVE.L A2,A0
MOVE.L (A0)+,(A1)+ ;copy R, G to stack
MOVE (A0)+,(A1)+ ;copy B to stack
PEA 4(SP) ;push the copy of the background RGB
_InvertColor ;get the furthest thing from it
PEA 4(SP) ;pass pointer to hilite color
_Color2Index ;leave pixel on stack (hilite color)
@notSame
; set up pointers to color table, inverse color table and table resolution in locals
MOVE.L ([theGDevice]),A0 ;get a pointer to the current device
MOVE.L ([GDPMap,A0]),A1 ;get pixMap's handle
MOVE.L ([GDITable,A0]),A0 ;get the inverse color table's master pointer
MOVE ITabRes(A0),D0
MOVE D0,invSize(A6) ;save resolution of inverse color table
MOVEQ #16,D1
SUB D0,D1
MOVE D1,rtShift(A6) ;set up for Average, how far to shift mulu result
move.l a0,d0
_rTranslate24To32 ;strip high byte @@@@ BAL
MOVE.L d0,invColor(A6) ;save pointer to inverse color table
MOVE.L ([PMTable,A1]),A1 ;pointer to color table
LEA ctTable+rgb+red(A1),A1 ;location of "red" of first color in color table
move.l a1,d0
_rTranslate24To32 ;strip high byte @@@@ BAL
MOVE.L d0,colorTable(A6) ;save a pointer to the device colortable
MOVE.L D5,D2 ;COPY BK PIXEL
MOVE.L (SP),D4 ;copy of hilite pixel
;note that weÕre comparing against the port background (which may not be the drawing background)
MOVEQ #32,D1 ;GET SIZE OF A LONG
@nxtPixel
SUB D7,D1 ;SAY WE'VE DONE A PIXEL
BLE.S @done ;=>IT WAS THE LAST ONE
LSL.L D7,D2 ;PREPARE FOR NEXT BK PIXEL
OR.L D5,D2 ;INSTALL BK PIXEL
LSL.L D7,D4 ;shift hilite pixel up a notch
OR.L (SP),D4 ;add in a pixel to the low order pixel position
BRA.S @nxtPixel
@done
MOVE.L D2,transColor(A6) ;save for transparent
MOVE.L D4,hilitColor(A6) ;save for hilite
ADD #10,SP ;throw away hilite pixel, rgb inverse
noArith
MOVEM.L (SP)+,D3-D7/A2-A3 ;RESTORE REGS
; UNLK A4 ;DONE WITH STACK FRAME
RTS ;JUST RETURN
; GET COLORS FROM PORT AND MAP FOR PROPER DEPTH
; MAP THE RGB IN THE OLD-STYLE COLOR INTO A NEW COLOR INDEX
; KEEP INTENSITY IN BIT 9.
; THE BITS IN THE OLD STYLE COLORS ARE IN THE ORDER:
; BIT 0: BK/FG BIT (0 IF WHITE, ELSE 1)
; BIT 1: NOT BK/FG BIT (1 IF WHITE, ELSE 0)
; RGB BITS
; BIT 2: NOT BLUE
; BIT 3: NOT GREEN
; BIT 4: NOT RED
; CMY BITS
; BIT 5: BLACK BIT
; BIT 6: YELLOW BIT
; BIT 7: MAGENTA BIT
; BIT 8: CYAN BIT
; INTENSITY BIT
; BIT 9: 0 = FULL INTENSITY, 1 = HALF INTENSITY
mapToColor
LSR #1,D0 ;CHECK FOR WHITE (I CMYB rgbw)
BCS.S @0 ;=>NOT WHITE
OR #$00E0,D0 ;ELSE SET WHITE BITS (CMY = 111)
@0 LSR #5,D0 ;SHIFT ICMYÊINTO LOW NIBBLE
AND #$7,D0 ;CLEAR ALL BUT LOW NIBBLE
MOVE.L QDColors,A0 ;GET DEFAULT COLORS
MOVE.L 4(A0,D0*8),-(SP) ;PUSH GREEN, BLUE
MOVE.W 2(A0,D0*8),-(SP) ;PUSH RED
CLR.L -(SP) ;MAKE ROOM FOR FUNCTION RESULT
PEA 4(SP) ;POINT TO VAR RGB
_COLOR2INDEX ;CONVERT IT TO AN INDEX
MOVE.L (SP)+,D0 ;GET MAPPED COLOR
ADDQ #6,SP ;STRIP COLORSPEC
RTS
xrgbBlack DC.W $0000,$0000,$0000 ;BLACK
xrgbWhite DC.W $FFFF,$FFFF,$FFFF ;WHITE
xrgbGray DC.W $7FFF,$7FFF,$7FFF ;GRAY
;----------------------------------------------------------------
;
; Dispatcher for alpha channel utility routines (Trap $ABC0)
; Added in revision <17>.
;
; as seen in QDciPatchROM.a <sm 6/9/92>stb
AlphaDispatch PROC EXPORT
IMPORT RSetHSize
IMPORT SetForeAlpha ; <SM4>.start
IMPORT SetBackAlpha
IMPORT GetForeAlpha
IMPORT GetBackAlpha
IMPORT GetForeAlphaMask
IMPORT GetBackAlphaMask ; <SM4>.end
JMP @dispatch(PC,D0.W*4)
@dispatch
BRA.W AlphaVersion
BRA.W SetForeStream
BRA.W SetForeTransparency
BRA.W SetBackStream
BRA.W SetBackTransparency
BRA.W GetForeStream
BRA.W GetForeTransparency
BRA.W GetBackStream
BRA.W GetBackTransparency
BRA.W ResizeGrafVars
BRA.W GetStreamMode
BRA.W SetForeAlpha ; <SM4>.start
BRA.W SetBackAlpha
BRA.W GetForeAlpha
BRA.W GetBackAlpha
BRA.W GetForeAlphaMask
BRA.W GetBackAlphaMask ; <SM4>.end
;
; FUNCTION AlphaVersion:INTEGER;
;
AlphaVersion
MOVE.W #$0100,4(SP) ;return version 1.0
RTS
;
; PROCEDURE SetForeStream(streamID: LongInt);
; PROCEDURE SetBackStream(streamID: LongInt);
;
SetForeStream
MOVEQ #foreStream,D1 ;point at foreStream/foreRatio in grafvars
BRA.S SetStream ;jump into common code
SetBackStream
MOVEQ #backStream,D1 ;point at backStream/backRatio in grafvars
SetStream
BSR.S SetSub
BEQ.S @exit
MOVE.L 4(SP),(A0) ;move stream from stack to grafvars
@exit RTD #4 ;clean off stack and return
;
; PROCEDURE SetForeTransparency(streamRatio: INTEGER);
; PROCEDURE SetBackTransparency(streamRatio: INTEGER);
;
SetForeTransparency
MOVEQ #foreRatio,D1 ;point at foreStream/foreRatio in grafvars
BRA.S SetTrans ;jump into common code
SetBackTransparency
MOVEQ #backRatio,D1 ;point at backStream/backRatio in grafvars
SetTrans
BSR.S SetSub
BEQ.S @exit
MOVE.W 4(SP),(A0) ;move ratio from stack to grafvars
@exit RTD #2 ;clean off stack and return
SetSub MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @exit ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @exit ;if null, exit
MOVE.L D0,A0 ;move grafvars handle to more useful register
MOVE.L (A0),A0 ;deref it
BTST #PmNewGVBit-8,pmFlags(A0) ;check for new grafvars flag
BNE.S @1 ;if it was set, no need to grow grafvars
MOVE.L D0,-(SP) ;save grafvars handle
MOVE.L D0,-(SP) ;push grafvars handle for resize call
_ResizeGrafVars ;grow grafvars to new size
MOVE.L (SP)+,A0 ;restore grafvars handle
MOVE.L (A0),A0 ;deref it again
@1: ADD.W D1,A0 ;bump to field being modified
ST D0 ;set do it flag to true
RTS
@exit CLR D0 ;set do it flag to false
RTS
;
; PROCEDURE GetForeStream: INTEGER;
; PROCEDURE GetBackStream: INTEGER;
;
GetForeStream
MOVEQ #foreStream,D1 ;point at foreStream in grafvars
BRA.S GetStream ;jump into common code
GetBackStream
MOVEQ #backStream,D1 ;point at backStream in grafvars
GetStream
MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @default ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @default ;if null, return default info
MOVE.L D0,A0 ;move grafvars handle to more useful register
MOVE.L (A0),A0 ;deref it
BTST #PmNewGVBit-8,pmFlags(A0) ;check for new grafvars flag
BEQ.S @default ;if it was clear, return default info
ADD.W D1,A0 ;bump to either foreStream or backStream
MOVE.L (A0),4(SP) ;move stream from grafvars to user variable
RTS
@default
CLR.L 4(SP) ;move default stream to user variable
RTS
;
; PROCEDURE GetForeTransparency: INTEGER;
; PROCEDURE GetBackTransparency: INTEGER;
;
GetForeTransparency
MOVEQ #foreRatio,D1 ;point at foreRatio in grafvars
BRA.S GetTrans ;jump into common code
GetBackTransparency
MOVEQ #backRatio,D1 ;point at backRatio in grafvars
GetTrans
MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @default ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @default ;if null, return default info
MOVE.L D0,A0 ;move grafvars handle to more useful register
MOVE.L (A0),A0 ;deref it
BTST #PmNewGVBit-8,pmFlags(A0) ;check for new grafvars flag
BEQ.S @default ;if it was clear, return default info
ADD.W D1,A0 ;bump to either foreStream or backStream
MOVE.W (A0),4(SP) ;move ratio from grafvars to user variable
RTS
@default
CLR.W 4(SP) ;move default ratio to user variable
RTS
;
; On Entry:
; (on stack): grafvars handle
;
; ONLY TRASHES D0/A0
;
ResizeGrafVars
MOVE.L 4(SP),A0 ;get grafVars handle
MOVE.L (A0),A0 ;deref grafvars handle
BSET #PmNewGVBit-8,pmFlags(A0) ;check new grafvars flag and set it if not already
BNE.S @exit ;if it was set, then we are too
MOVE.L 4(SP),A0 ;get grafVars handle agian
MOVE.L #newGrafVarRec,D0 ;get size of new grafvars
BSR RSetHSize ;set the handle to be that size
MOVE.L (A0),A0 ;deref again
LEA foreStream(A0),A0 ;bump to beginning of our stuff
CLR.L (A0)+ ;clear foreStream
CLR.L (A0)+ ;clear foreRatio, half of backStream
CLR.L (A0)+ ;clear half of backStream, backRatio
CLR.W (A0)+ ;clear stream mode and filler
@exit RTD #4 ;all done
;
; On Entry:
; D1: penmode (not necessarily from the current port)
;
; On Exit:
; D1: penmode stripped of alpha transfer bits
;
GetStreamMode
MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @exit ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @exit ;if null, exit
MOVE.L D0,-(SP) ;save copy of grafvars handle
MOVE.L D0,-(SP) ;put grafVars handle on stack
_ResizeGrafVars ;make sure grafvars are big enough
MOVE.L (SP)+,A0 ;get grafVars handle off stack
MOVE.L (A0),A0 ;dereference it
MOVE.W D1,D0 ;make copy of penmode
LSR.W #8,D0 ;right align alpha bits
AND.W #3,D0 ;mask off all but alpha bits
MOVE.B D0,streamMode(A0) ;put alphamode into streamMode
@exit AND.W #$FCFF,D1 ;remove alpha bits from penmode
RTS ;return stripped penmode
;
; On Entry:
; (on stack): pointer to streamID and ratio
; (on stack): pointer to where to put
; alphamask (long) and alphacolor (long)
;
StreamToMask PROC EXPORT
MOVE.L 8(SP),A0 ;get pointer to streamID/ratio
MOVE.L 4(SP),A1 ;get pointer to result destination
MOVE.W 4(A0),D0 ;get ratio
TST.L (A0) ;check if stream is graphics (zero)
BEQ.S @1 ;yes, skip
NOT.W D0 ;no, reverse context of transparency
@1: MOVE.W D0,D1
SWAP D0
MOVE.W D1,D0
MOVE.L THEGDEVICE,A0 ;get handle of current gdevice
MOVE.L (A0),A0 ;deref it
MOVE.L gdPMap(A0),A0 ;get handle of gdevice's pixmap
MOVE.L (A0),A0 ;deref it
MOVE.W pmPixelSize(A0),D1 ;get its pixel size
CMP #16,D1 ;is it 16-bits per pixel?
BEQ.S @16bits
MOVE.L MaskBC,D1 ;get 32-bits per pixel not mask
BRA.S @2
@16bits MOVE.L #$7FFF7FFF,D1 ;get 16-bits per pixel not mask
@2: NOT.L D1 ;reverse the mask
AND.L D1,D0 ;mask alpha color
MOVE.L D1,(A1)+ ;save alphamask
MOVE.L D0,(A1)+ ;save alphacolor
RTD #8
; ; <SM4>.start
; FUNCTION SetForeAlpha(type: LONG; value: INTEGER) : OSErr
;
; On Entry:
; (on stack): return address
; (on stack): unsigned short alpha value
; (on stack): long alpha type
; (on stack): OSErr result
;
; On Exit:
; (on stack}: OSErr result
SetForeAlpha PROC EXPORT
alpha EQU 4 ;[unsigned word] alpha value
type EQU alpha+2 ;[long] alpha type
error EQU type+4 ;[word] OSErr result
paramSize EQU type ;size of parameters
clr.w error(sp) ;clear error result
move.w alpha(sp),-(sp) ;push alpha value
_SetForeTransparency ;set the foreground transparency
RTD #paramSize
;
; FUNCTION SetBackAlpha(type: LONG; value: INTEGER) : OSErr
;
; On Entry:
; (on stack): return address
; (on stack): unsigned short alpha value
; (on stack): long alpha type
; (on stack): OSErr result
;
; On Exit:
; (on stack}: OSErr result
SetBackAlpha PROC EXPORT
alpha EQU 4 ;[unsigned word] alpha value
type EQU alpha+2 ;[long] alpha type
error EQU type+4 ;[word] OSErr result
paramSize EQU type ;size of parameters
clr.w error(sp) ;clear error result
move.w alpha(sp),-(sp) ;push alpha value
_SetBackTransparency ;set the background transparency
RTD #paramSize
;
; FUNCTION GetForeAlpha(VAR type: LONG; VAR value: INTEGER) : OSErr
;
; On Entry:
; (on stack): return address
; (on stack): long *alpha
; (on stack): long *type
; (on stack): OSErr result
;
; On Exit:
; (on stack}: OSErr result
GetForeAlpha PROC EXPORT
alpha EQU 4 ;[long] alpha value
type EQU alpha+4 ;[long] alpha type
error EQU type+4 ;[word] OSErr result
paramSize EQU type ;size of parameters
clr.w error(sp) ;clear error result
subq #2,sp ;room for short result
_GetForeTransparency ;get the foreground transparency
move.w (sp)+,d0 ;get alpha result
move.l alpha(sp),a0 ;get alpha var
move.w d0,(a0) ;write alpha
move.l type(sp),a0 ;get type var
move.l #'vido',(a0) ;write type
RTD #paramSize
;
; FUNCTION GetBackAlpha(VAR type: LONG; VAR value: INTEGER) : OSErr
;
; On Entry:
; (on stack): return address
; (on stack): long *alpha
; (on stack): long *type
; (on stack): OSErr result
;
; On Exit:
; (on stack}: OSErr result
GetBackAlpha PROC EXPORT
alpha EQU 4 ;[long] alpha value
type EQU alpha+4 ;[long] alpha type
error EQU type+4 ;[word] OSErr result
paramSize EQU type ;size of parameters
clr.w error(sp) ;clear error result
subq #2,sp ;room for short result
_GetBackTransparency ;get the background transparency
move.w (sp)+,d0 ;get alpha result
move.l alpha(sp),a0 ;get alpha var
move.w d0,(a0) ;write alpha
move.l type(sp),a0 ;get type var
move.l #'vido',(a0) ;write type
RTD #paramSize
;
; FUNCTION GetForeAlphaMask(grafVars: Handle,mask^: LONG) : OSErr
;
; On Entry:
; (on stack): return address
; (on stack): long mask ptr
; (on stack): long grafVars Handle
; (on stack): OSErr result
;
; On Exit:
; (on stack}: OSErr result
;
; Note:
; We assume that the GrafVars are expanded
;
GetForeAlphaMask PROC EXPORT
alphaMask EQU 4 ;[long] grafVars handle
GrafVarsH EQU alphaMask+4 ;[long] grafVars handle <SM5>
error EQU grafVars+4 ;[word] OSErr result
paramSize EQU grafVars ;size of parameters
clr.w error(sp) ;clear error
move.l ([GrafVarsH,sp]),a0 ;get ptr to GrafVars
pea foreStream(a0) ;push pointer to foreground stream and ratio
move.l alphaMask+4(sp),-(sp) ;push ptr to stream and mask
_StreamToMask
RTD #paramSize
;
; FUNCTION GetBackAlphaMask(grafVars: Handle,mask^: LONG) : OSErr
;
; On Entry:
; (on stack): return address
; (on stack): long mask ptr
; (on stack): long grafVars Handle
; (on stack): OSErr result
;
; On Exit:
; (on stack}: OSErr result
;
; Note:
; We assume that the GrafVars are expanded
;
GetBackAlphaMask PROC EXPORT
alphaMask EQU 4 ;[long] grafVars handle
GrafVarsH EQU alphaMask+4 ;[long] grafVars handle <SM5>
error EQU grafVars+4 ;[word] OSErr result
paramSize EQU grafVars ;size of parameters
clr.w error(sp) ;clear error
move.l ([GrafVarsH,sp]),a0 ;get ptr to GrafVars
pea backStream(a0) ;push pointer to background stream and ratio
move.l alphaMask+4(sp),-(sp) ;push ptr to stream and mask
_StreamToMask
RTD #paramSize ; <SM4>.end
GetCPixel FUNC EXPORT
EXPORT GETPIXEL
IMPORT HideCursor,ShowCursor,PortToMap
;---------------------------------------------------------
;
; FUNCTION GetPixel(h,v: INTEGER): BOOLEAN;
; PROCEDURE GetCPixel(h,v: INTEGER; myColor: RGBColor);
;
; Returns TRUE if the pixel at (h,v) is set to black.
; h and v are in local coords of the current grafport.
;
; WATCH OUT FOR STACK TRICKERY WHEN GETCPIXEL CALLS GETPIXEL!!
;
; CLOBBERS A0,A1,D0,D1,D2
;
; reflect the patch from QDciPatchROM.a so that SwapMMUMode is called <sm 6/9/92>stb
;Êif the pixmap needs 32-bit addressing (pmVersion = 4). <sm 6/9/92>stb
PARAMSIZE EQU 4
RETURN EQU PARAMSIZE+8 ;ADDRESS OF BOOLEAN/RGBCOLOR
HLOC EQU PARAMSIZE+8-2 ;HORIZONTAL POSITION
VLOC EQU HLOC-2 ;VERTICAL POSITION
VARSIZE EQU 0 ;TOTAL SIZE OF LOCALS
MOVE.L 8(SP),-(SP) ;PUSH H,V
MOVEQ #1,D2 ;ROUTINE = GETCPIXEL
BSR.S SHARE ;USE COMMON CODE
RTD #8 ;STRIP PARAMS AND RETURN
GETPIXEL
MOVEQ #0,D2 ;ROUTINE = GETPIXEL
SHARE LINK A6,#VARSIZE ;ALLOCATE STACKFRAME
MOVEM.L D4-D6/A2-A3,-(SP) ;SAVE WORK REGISTERS
MOVE.L THEGDEVICE,-(SP) ;SAVE CURRENT GRAFDEVICE
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET THEPORT
_PORTTOMAP ;GET BIT/PIXMAP IN A0
; GET GLOBAL COORDINATES OF VLOC INTO D4 AND HLOC INTO D5
OLDRB MOVE VLOC(A6),D4 ;GET VERTICAL
SUB BOUNDS+TOP(A0),D4 ;CONVERT TO GLOBAL COORDS
MOVE HLOC(A6),D5 ;GET HORIZ COORD
SUB BOUNDS+LEFT(A0),D5 ;CONVERT TO GLOBAL
; IS IT FROM THE SCREEN?
MOVE.L MAINDEVICE,A2 ;GET MAIN DEVICE
MOVE.L (A2),A2 ;POINT TO IT
MOVE.L GDPMAP(A2),A2 ;GET PIXMAP HANDLE
MOVE.L (A2),A2 ;POINT TO PIXMAP
MOVE.L BASEADDR(A0),D1 ;GET PORT'S BASEADDR
CMP.L BASEADDR(A2),D1 ;SAME AS SCREEN'S?
seq.b -(sp) ;push crsrFlag @@@@ BAL 14Apr88
move.l a0,a3 ;save pixmap in a3
BNE.S NOTSCRN ;=>NO, NOT SCREEN
; IT IS FROM THE SCREEN! Shield the Cursor. @@@@ BAL 14Apr88
MOVE D5,-(SP) ;PUSH GLOBAL LEFT
MOVE D4,-(SP) ;PUSH GLOBAL TOP
MOVE D5,-(SP) ;PUSH GLOBAL RIGHT
MOVE D4,-(SP) ;PUSH GLOBAL BOTTOM
MOVE.L SP,A0
CLR.L -(SP)
MOVE.L A0,-(SP)
CLR.L -(SP)
MOVE.L #$80000,D0
DC.W $ABE0 ;_QDExtensions2
MOVE.L (SP)+,D6
ADDQ #8,SP
MOVE.L DEVICELIST,A3 ;GET FIRST IN DEVICE LIST
DONXT MOVE.L (A3),A2 ;POINT TO DEVICE
TST GDFLAGS(A2) ;IS DEVICE ACTIVE?
BPL.S NXTDEV ;=>NO, NOT ACTIVE
LEA GDRECT(A2),A1 ;POINT TO DEVICE'S RECT
CMP (A1)+,D4 ;IS VERTICAL < GDRECT.TOP ? <SMC 18SEP90> <11>
BLT.S NXTDEV ;=>YES, CHECK NEXT DEVICE <SMC 18SEP90> <11>
CMP (A1)+,D5 ;IS HORIZONTAL < GDRECT.LEFT ? <SMC 18SEP90> <11>
BLT.S NXTDEV ;=>YES, CHECK NEXT DEVICE <SMC 18SEP90> <11>
CMP (A1)+,D4 ;IS VERTICAL >= GDRECT.BOTTOM ?
BGE.S NXTDEV ;=>YES, CHECK NEXT DEVICE
CMP (A1)+,D5 ;IS HORIZONTAL >= GDRECT.RIGHT ?
BLT.S GOTDEV ;=>NO, FOUND DEVICE
NXTDEV MOVE.L GDNEXTGD(A2),D0 ;GET HANDLE TO NEXT DEVICE
MOVE.L D0,A3 ;KEEP IN A3
BNE.S DONXT ;=>THERE IS A DEVICE
BRA DONE ;=>DEVICE NOT FOUND, JUST RETURN
; FOUND THE DEVICE! SET DEVICE AND OFFSET POINT TO DEVICE LOCAL COORDINATES
GOTDEV MOVE.L A3,THEGDEVICE ;MAKE DEVICE CURRENT
LEA GDRECT(A2),A1 ;POINT TO DEVICE'S RECT
SUB (A1)+,D4 ;OFFSET VERTICAL
SUB (A1)+,D5 ;OFFSET HORIZONTAL
MOVE.L GDPMAP(A2),A3 ;GET PIXMAP HANDLE
MOVE.L (A3),d0 ;POINT TO PIXMAP
_rTranslate24To32 ;strip off high byte @@@@ BAL 14Apr88
move.l d0,a3
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
Needs32BitMode
move.b #$ff,(sp) ;flag the fact that MMU mode must be swapped <KON 20JUN90>
moveq #true32b,d0 ;switch to 32 bit addressing
move.w d2,-(sp) ;save color/ bw flag across call
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a2, d0/d2)
move.w (sp)+,d2 ;restore flag in d2
;save previous state in d0 for later
bra.s MMUModeOK
NOTSCRN
;
; Check if pixmap needs 32-bit addressing <KON 20JUN90>
;
baseAddr32Bit EQU 2
tst.w rowbytes(a3) ; <KON 20JUN90>
bpl.s MMUModeOK ;it's a bitmap <KON 20JUN90>
btst #baseAddr32Bit,pmVersion+1(a3) ; <KON 20JUN90>
bne.s Needs32BitMode ;pixmap needs 32-bit addressing <KON 20JUN90>
MMUModeOK
MOVE ROWBYTES(A3),D1 ;GET ROWBYTES
AND #nuRBMask,D1 ;AND MASK OFF FLAG BITS
MULU D4,D1 ;CALC VERT * ROWBYTES
MOVE.L BASEADDR(A3),A1 ;GET BASEADDR
ADD.L D1,A1 ;ADD VERTICAL OFFSET
MOVEQ #1,D1 ;ASSUME PIXELSIZE = 1
TST ROWBYTES(A3) ;NEW PIXMAP?
BPL.S OLDMAP ;=>NO, USE PIXSIZE = 1
MOVE PIXELSIZE(A3),D1 ;ELSE GET TRUE PIXELSIZE
OLDMAP MULU D1,D5 ;PIXEL OFFSET = PIXELSIZE*HLOC
BFEXTU (A1){D5:D1},D4 ;EXTRACT THE PIXEL
tst.b (sp)
beq.s @noSwap ;need to swap modes again?
;previous MMU state still in d0
move.l d2,d5 ;protect flag in d5
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a2, d0/d2)
move.l d5,d2 ;restore flag
@noSwap TST D2 ;COLOR OR NOT?
BEQ.S NOCOLOR ;=>NO COLOR
MOVE.L D4,-(SP) ;PUSH INDEX
MOVE.L RETURN+4(A6),-(SP) ;POINT TO RGBCOLOR
_INDEX2COLOR ;CONVERT THE INDEX TO A COLOR
BRA.S DONE ;=>RESTORE CURSOR AND RETURN
NOCOLOR cmp.w #16,pixelType(a3) ;direct device?
bne.s @clut ;no, don't hack pixel value
tst.l d4 ;is it all zeros?
seq d4 ;yes, flag black
bra.s @ret
@clut TST D4 ;ELSE TEST PIXEL
SNE D4 ;SET BOOLEAN RESULT
@ret NEG D4 ;MAKE $FF --> $01
MOVE.B D4,RETURN(A6) ;AND RETURN IT
DONE tst.b (sp)+ ;pop and check crsrFlag
beq.s @noShow ;need to show cursor?
move.l D6,-(SP)
move.l #$40001,D0
dc.w $ABE0 ;_QDExtensions2
@noShow MOVE.L (SP)+,THEGDEVICE ;RESTORE CURRENT GRAFDEVICE
MOVEM.L (SP)+,D4-D6/A2-A3 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'GETCPIXEL'
Translate24To32 PROC EXPORT ;BAL 26Dec88
IF forROM THEN ; SuperMario is 32 bit only ROM
RTS
ELSE
;-------------------------------------------------------
;
; FUNCTION Translate24To32(Addr24:long) : Addr32;
;
; Translate a 24 Bit address to a valid 32 Bit address.
; (Will be toolbox trap $AB03)
;
; INPUT D0=Addr24;
; OUTPUT D0=Addr32;
;
; All registers preserved
;
; Translation algorithm from Mac Family Hardware Reference Table 17-1:
;
; Old first 3 nibbles New first 3 nibbles
; ------------------- -------------------
; xx0 000
; : :
; xx7 007
; xx8 400-->408 for safety in 24 bit mode; also since the emulator doesn't alias
; xx9 F90
; : :
; xxE FE0
; xxF 500
;
;
;
; NOTE: Unlike _StripAddress, this routine does not necessarily
; return an address which can also be used in 24 bit mode.
; Furthermore, Translate24To32 can not be called meaningfully
; with the result of a previous translation.
;
;
AND.L Lo3Bytes,D0 ;Clean high byte for fast exit
BCLR #23,D0 ;Is the address in RAM?
BNE.S @NotRam ;no, go patch up address
RTS ;quick exit
@NotRam
MOVE.W D1,-(SP) ;Save a work register
MOVE.W #12,D1 ;prepare for shift and clear our word, Scotty
ROL.L D1,D0 ;get 3rd nibble
MOVE.B D0,D1 ;keep for indexing
beq.s @inROM ;handle ROM case for emulator
LSR.L #4,D0 ;clear out 3rd nibble
MOVE.B (TRANSLATE,PC,D1.W),D0 ;compute new high byte
MOVE.W (SP)+,D1 ;Restore work register
ROR.L #8,D0 ;reposition high byte
RTS
@inROM
or.w #$0408,d0 ;set up ROM address
ROR.L #4,D0 ;restore address
ROR.L #8,D0 ;restore address
MOVE.W (SP)+,D1 ;Restore work register
RTS
TRANSLATE
DC.B $40,$F9,$FA,$FB,$FC,$FD,$FE,$50
ENDIF ; forROM
ElsieTranslate24To32 PROC EXPORT ;JJ&BA 2/23/90
IF forROM THEN ; SuperMario is 32 bit only ROM
RTS
ELSE
;-----------------------------------------------------------------------------------------
;
; FUNCTION ElsieTranslate24To32(Addr24: long): Addr32;
;
; Translate an Elsie 24-bit address to a valid Elsie 32-bit address.
;
; INPUT D0=Addr24;
; OUTPUT D0=Addr32;
;
; All other registers preserved
;
; Translation algorithm from Elsie Hardware ERS:
;
; High 3 nibbles (24) High 3 nibbles (32)
; ------------------- -------------------
; xx0 000 (RAM)
; : : :
; xx9 009 (RAM)
; -------------------------------------------
; xxA 40A (ROM)
; : : :
; xxD 40D (ROM)
; -------------------------------------------
; xxE FE0 (Direct Slot)
; xxF 50F (I/O Space)
;
; NOTE: Unlike _StripAddress, this routine does not necessarily
; return an address which can also be used in 24 bit mode.
; Furthermore, Translate24To32 can not be called meaningfully
; with the result of a previous translation.
;
AND.L Lo3Bytes,D0 ;Clean high byte for fast exit
BCLR #23,D0 ;Is the address in lower 8 MB of RAM?
BNE.S @LOOKUP ;no, go patch up address
RTS ;quick exit
@LOOKUP MOVE.W D1,-(SP) ;save a work register
SWAP D0 ;get relevant nibbles into low word
MOVE.W D0,D1 ;...and into index register
LSR.W #4,D1 ;move nibble 3 to use as index
ADD.W (@TABLE,PC,D1.W*2),D0 ;translate by adding table value
SWAP D0 ;move translated nibbles back to high word
MOVE.W (SP)+,D1 ;restore work register
RTS
@TABLE DC.W $0080,$0080,$4080,$4080,$4080,$4080,$FDA0,$5080
ENDIF ; forROM
StuffHex PROC EXPORT
;-------------------------------------------------------
;
; PROCEDURE STUFFHEX(THINGPTR: WORDPTR; S: STR255);
;
; CONVENIENCE ROUTINE TO STUFF HEX INTO ANY VARIABLE.
; BEWARE, NO RANGE-CHECKING.
;
MOVE.L 4(SP),A0 ;A0:=ADDR OF STRING
MOVE.L 8(SP),A1 ;A1:=THINGPTR
MOVE.L (SP),8(SP) ;CLEAN OFF STACK
ADD #8,SP ;POINT TO RETURN ADDR
MOVE.B (A0)+,D2 ;GET STRING LENGTH
AND #$00FE,D2 ;TRUNCATE LENGTH TO EVEN
BEQ.S ENDHEX ;QUIT IF LENGTH = 0
HEXLOOP BSR.S NEXTHEX ;GET HEX DIGIT AND CONVERT TO BINARY
MOVE.B D0,D1 ;SAVE MOST SIG DIGIT
BSR.S NEXTHEX ;GET HEX DIGIT AND CONVERT TO BINARY
LSL.B #4,D1 ;SHIFT MOST SIG INTO PLACE
ADD.B D0,D1 ;FILL IN LS NIBBLE
MOVE.B D1,(A1)+ ;STUFF BYTE INTO THING
SUB #2,D2 ;2 LESS CHARS TO GO
BNE.S HEXLOOP ;LOOP FOR STRING LENGTH
ENDHEX RTS ;RETURN TO PASCAL
;
; LOCAL ROUTINE TO GET NEXT HEX DIGIT AND CONVERT ASCII TO BINARY
;
NEXTHEX MOVE.B (A0)+,D0 ;GET HEX DIGIT FROM STRING
CMP.B #$39,D0 ;IS IT GTR THAN '9' ?
BLE.S SMALL ;NO, DO IT
ADD.B #9,D0 ;YES, ADD CORRECTION
SMALL AND.B #$F,D0 ;TREAT MOD 16, EVEN LOWER CASE OK
RTS
XorSlab PROC EXPORT
;-----------------------------------------------------------
;
; LOCAL PROCEDURE XorSlab(bufAddr: Ptr; left,right: INTEGER);
;
; Enter with:
;
; A0: bufAddr
; D0: pixelShift
; D3: left coord
; D4: right coord
;
; Clobbers: A0,D0,D1,D3,D4,D5,D6
;
; Calc bitcount. If <= 32 then use single BFCHG
ext.l d4 ; clear out high word
ext.l d3 ; ditto
LSL.l D0,D4 ; convert left pixel to left bit
LSL.l D0,D3 ; convert right pixel to right bit
MOVE.l D4,D0 ; get right edge
SUB.l D3,D0 ; get bitcount (right-left)
BLE.S DONE ; => none to do
CMP.l #32,D0 ; BFCHG can only do 32 bits
BGT.S NOTIN1 ; => slab > 32 bits
BFCHG (A0){D3:D0} ; XOR from left to right
DONE RTS ; and return
; calc left field, right field, and number of longs in middle
NOTIN1 MOVEQ #$1F,D1 ; get useful value
MOVE D3,D0 ; get a copy of left edge
AND D1,D0 ; get left edge mod 32
MOVEQ #-1,D5 ; fill leftmask with ones
LSR.L D0,D5 ; D5 = LEFTMASK
MOVE D4,D0 ; get a copy of right edge
AND D1,D0 ; get right edge mod 32
MOVEQ #-1,D6 ; fill rightmask with ones
LSR.L D0,D6 ; shift in 0's from left
NOT.L D6 ; D6 = RIGHTMASK
ASR.l #5,D3 ; convert left dots to longs
ASR.l #5,D4 ; convert right dots to longs
SUB D3,D4 ; LONGCOUNT = rightlong-leftlong
SUBQ #1,D4 ; get longcount-1 for DBRA
LSL #2,D3 ; convert left to bytes
ADD D3,A0 ; add to bufAddr
; do the left, the middle, then the right part of the slab
EOR.L D5,(A0)+ ; XOR the left part of the slab
BRA.S TEST ; see if there is a middle one
NXTLONG NOT.L (A0)+ ; do a middle long
TEST DBRA D4,NXTLONG ; any longs left?
EOR.L D6,(A0) ; XOR the right part of the slab
RTS
DrawSlab PROC EXPORT
EXPORT SlabMode,FastSlabMode
EXPORT slMASK8,slMASK9,slMASK10,slMASK11,slXMASK8,slXMASK9,slXMASK10,slXMASK11
EXPORT slAvg,slAddPin,slAddOver,slSubPin,slTransparent,slMax,slSubOver,slMin,slHilite
EXPORT slArith16Tab,slArith32Tab
;--------------------------------------------------------------
;
; LOCAL PROCEDURE DRAWSLAB
;
; INPUTS:
;
; D0: shift/scratch A0:
; D1: left A1: DSTLEFT, clobbered
; D2: right A2: RGNBUFFER, clobbered
; D3: scratch A3: MINRECT
; D4: FGCOLOR A4: MODECASE
; D5: BKCOLOR A5:
; D6: PATTERN A6: SHARED STACKFRAME
; D7: A7: stack
;
; CLOBBERS: D0-D3,A0,A1,A2
;
; CLIP LEFT AND RIGHT TO MINRECT:
;
; CALLED BY DRAWARC AND DRAWLINE
;
; HERE ARE THE SHARED LOCALS FOR THOSE ROUTINES:
;--------------------------------------------------------------
&CurFile SETC 'DRAWSLAB'
INCLUDE 'DrawingVars.a'
;--------------------------------------------------------------
CMP LEFT(A3),D1 ;IS LEFT < MINRECT.LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
MOVE LEFT(A3),D1 ;YES, LEFT := MINRECT.LEFT
LEFTOK CMP RIGHT(A3),D2 ;IS RIGHT > MINRECT.RIGHT ?
BLE.S RIGHTOK ;NO, CONTINUE
MOVE RIGHT(A3),D2 ;YES, RIGHT := MINRECT.RIGHT
RIGHTOK CMP D2,D1 ;IS LEFT >= RIGHT ?
BGE.S DONESLAB ;YES, QUIT
; GOT LEFT AND RIGHT, CONVERT PIXELS TO BITS
ext.l d1 ;compute result in a long <BAL 15Sep88>
ext.l d2 ;compute result in a long <BAL 15Sep88>
LSL.l D0,D1 ;CONVERT LEFT PIXELS TO BITS
move.l d1,slabLeft(a6) ;copy for below, arith setup <BAL 17Jan89>
LSL.l D0,D2 ;CONVERT RIGHT PIXELS TO BITS
; SET UP LEFTMASK AND RIGHTMASK
MOVEQ #$1F,D0 ;NEED RIGHT MOD 32
AND D0,D1 ;GET LEFT MOD 32
MOVEQ #-1,D3 ;GET ONES INTO D3
LSR.L D1,D3 ;GET LEFTMASK IN D3
AND D2,D0 ;GET RIGHT MOD 32
MOVEQ #-1,D1 ;GET ONES INTO D1
LSR.L D0,D1 ;GET LEFTMASK IN D1
NOT.L D1 ;TURN INTO A RIGHTMASK
MOVE.l slabLeft(a6),D0 ;GET LEFT IN D0 <BAL 15Sep88>
;
; CALC WORDCOUNT, DSTPTR, MASKPTR, AND TAKE CASE JUMP
;
ASR.l #5,D2 ;CONVERT RIGHT TO LONGS <BAL 15Sep88>
ASR.l #5,D0 ;CONVERT LEFT TO LONGS <BAL 15Sep88>
SUB D0,D2 ;CALC LONG COUNT
ADD D0,D0 ;DOUBLE FOR WORDS
ADD D0,D0 ;QUAD FOR BYTES
ADD D0,A1 ;OFFSET DSTPTR
ADD D0,A2 ;OFFSET MASKPTR
;D0 USED BY BIG PATTERN ROUTINES
TST D2 ;SET Z-FLAG BASED ON WORDCOUNT
JMP (A4) ;TAKE MODECASE TO DRAW SLAB
DONESLAB RTS
;---------------------------------------------------------
;
; INTERFACE TO EACH SCAN LINE ROUTINE:
;
; ENTER WITH Z-FLAG SET IF ALL IN ONE LONG
;
; INPUTS: A1: DSTPTR
; A2: MASKPTR
; D1: RIGHTMASK
; D2: LONGCNT
; D3: LEFTMASK
; D4: FGCOLOR
; D5: BKCOLOR
; D6: PATTERN
;
; CLOBBERS: D0,D3,D2,A1,A2
; A3,D6 (BUT NOT IN FASTSLAB)
;
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST
;
; Slab copy using alpha mask <17>
;
; This exact code is in QDciROMPatches.a
slMASK8A
MOVE.L alphaMask(A6),D0 ;get alpha mask
AND.L D0,D1 ;clip left mask with alpha mask
AND.L D0,D3 ;clip right mask with alpha mask
MOVE.L D0,A0 ;save copy of alpha mask
TST D2 ;re-test long count
BRA.S DO8A
END8A AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
NEXT8A MOVE.L D6,D0 ;GET PATTERN DATA
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
AND.L D3,D0 ;MASK PATTERN DATA
NOT.L D3 ;MAKE NOTMASK
AND.L (A1),D3 ;AND NOTMASK WITH OLD DST
OR.L D0,D3 ;FILL HOLE WITH PATTERN
MOVE.L D3,(A1)+ ;UPDATE DST
MOVE.L A0,D3 ;FLUSH MASK to alpha mask
SUB #1,D2 ;DEC LONG COUNT
DO8A BGT NEXT8A ;LOOP FOR ALL LONGS IN ROW
BEQ END8A ;DO LAST LONG WITH MASK
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 8 OR 12: BIG PATTERN --> DST
;
; Slab copy using alpha mask <17>
;
slXMASK8A
MOVE D7,-(SP) ;SAVE WORK REGISTER
MOVE PATHMASK(A6),D7 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D7,D6 ;MASK INDEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.L PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
MOVE.L alphaMask(A6),D0 ;get alpha mask
AND.L D0,D1 ;clip left mask with alpha mask
AND.L D0,D3 ;clip right mask with alpha mask
MOVE.L D0,A0 ;save copy of alpha mask
TST D2 ;re-test long count
BRA.S XDO8A
XEND8A AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
XNEXT8A MOVE.L 0(A3,D6),D0 ;GET PATTERN DATA
ADDQ #4,D6 ;BUMP PATTERN INDEX
AND D7,D6 ;MASK INDEX INTO PATTERN
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
AND.L D3,D0 ;MASK PATTERN DATA
NOT.L D3 ;MAKE NOTMASK
AND.L (A1),D3 ;AND NOTMASK WITH OLD DST
OR.L D0,D3 ;FILL HOLE WITH PATTERN
MOVE.L D3,(A1)+ ;UPDATE DST
MOVE.L A0,D3 ;FLUSH MASK to alpha mask
SUB #1,D2 ;DEC LONG COUNT
XDO8A BGT XNEXT8A ;LOOP FOR ALL LONGS IN ROW
BEQ XEND8A ;DO LAST LONG WITH MASK
MOVE (SP)+,D7 ;RESTORE WORK REGISTER
RTS
ALIGN Alignment
if 0 then
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST
;
END8 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
NEXT8 MOVE.L D6,D0 ;GET PATTERN DATA
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
AND.L D3,D0 ;MASK PATTERN DATA
NOT.L D3 ;MAKE NOTMASK
AND.L (A1),D3 ;AND NOTMASK WITH OLD DST
OR.L D0,D3 ;FILL HOLE WITH PATTERN
MOVE.L D3,(A1)+ ;UPDATE DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
slMASK8 BGT NEXT8 ;LOOP FOR ALL LONGS IN ROW
BEQ END8 ;DO LAST LONG WITH MASK
RTS
endif
;******************************************************************************************
; QuickerDraw
; Scan line handler for clipped pattern fill copy mode (called by oval, rrect) -- trap $380
;Êjust like whatÕs in QDciPatchROM.a <sm 6/9/92>stb
FillClipScanLine
FCSL1 ; << PB452 BAL>>
FCSL2
slMASK8
AND.L (A2)+,D3 ;use left mask to start with
SUBQ #1,D2
BMI.S DoFCLast0
; special case the left edge
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
MOVE.L (A2)+,D3
SUBQ #1,D2
BMI.S DoFCLast0
; see if we're in the unclipped case; if so, use a faster loop
MOVE.L SEEKMASK(A6),A0 ;get seekRgn address
; CMP.W #$4E75,(A0) ;is it a RTS?
CMP.L #$343C7fff,(A0) ;is it "move.w #$7fff,d2"
BEQ.S DoFCUnclipped ;if so, handle specially
BRA.S FCNotOn1
; here's the loop -- use standard technique of special casing region masks
FCLineLoop
MOVE.L (A2)+,D3 ;fetch region mask
BEQ.S FCOff ;if all zero, can optimize
FCNotOff1
CMP.L MINUSONE,D3 ;all ones? << PB452 BAL>>
BEQ.S FCOn ;if so, optimize
FCNotOn1
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
DBRA D2,FCLineLoop
; handle the last one, using the mask in D1
DoFCLast
MOVE.L (A2)+,D3
DoFCLast0
AND.L D1,D3 ;use right mask
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
RTS
; handle the case of an all zero region mask
FCOff
ADDQ #4,A1 ;skip over it
SUBQ #1,D2
BMI.S DoFCLast
FCOffLoop
MOVE.L (A2)+,D3
BNE.S FCNotOff1
ADDQ #4,A1 ;skip it
DBRA D2,FCOffLoop
BRA.S DoFCLast
; handle the case of an all one's region mask
FCOn
MOVE.L D6,(A1)+
SUBQ #1,D2
BMI.S DoFCLast
FCOnLoop
MOVE.L (A2)+,D3
CMP.L MINUSONE,D3 ; << PB452 BAL>>
BNE.S FCNotOn1
MOVE.L D6,(A1)+
DBRA D2,FCOnLoop
BRA.S DoFCLast
; handle the unclipped case with faster unwound code
DoFCUnclipped
LEA 0(A2,D2.W*4),A2 ;bump region ptr
ADDQ #1,D2 ;compute count to do
CMP.W #8,D2
BLT.S FinishFCUnClip
MOVE.W D2,D0
LSR #3,D0 ;divide by 8
SUBQ #1,D0 ;bias for DBRA
FCUnClipLoop
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
DBRA D0,FCUnClipLoop
; now finish up the last 7 or less
FinishFCUnClip
AND #7,D2
EOR #7,D2
JMP FinishFCUCTab(D2.W*2)
FinishFCUCTab
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
BRA.S DoFCLast
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 9 OR 13: PATTERN OR DST --> DST
;
END9 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
NEXT9 AND.L D6,D3 ;MASK PATTERN DATA
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
MOVE.L D3,D0 ;COPY MASKED, CLIPPED SRC
AND.L D4,D0 ;APPLY FG COLOR TO SRC
NOT.L D3 ;GET NOT MASKED, CLIPPED SRC
AND.L (A1),D3 ;USE TO PUNCH OUT DST
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;MOVE RESULT INTO DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
oldslMASK9
BGT NEXT9 ;LOOP FOR ALL LONGS IN ROW
BEQ END9 ;DO LAST LONG WITH MASK
RTS
;******************************************************************************************
; QuickerDraw
; Scan line handler for clipped pattern fill OR mode (called by oval, rrect) -- trap $381
; similar to above, but in OR mode. We can only handle if the foreground pattern
; is all ones; if so, use the copy mode routine to fill.
; just like whatÕs in QDciPatchROM.a <sm 6/9/92>stb
UseOld381
TST.W D2
bra.s oldslMASK9
FillClipOrLine
slMASK9
CMP.L #-1,D6 ;all foreground?
BNE.S UseOld381 ;if not, we can't handle
MOVE.L D4,D6 ;set up fill pattern
BRA slMASK8 ;use common code
;******************************************************************************************
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 10 OR 14: PATTERN XOR DST --> DST
;
END10 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
NEXT10 AND.L D6,D3 ;GET PATTERN DATA
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
EOR.L D3,(A1)+ ;XOR RESULT INTO DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
slMASK10
BGT NEXT10 ;LOOP FOR ALL LONGS IN ROW
BEQ END10 ;DO LAST LONG WITH MASK
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 11 OR 15: PATTERN BIC DST --> DST
;
END11 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
NEXT11 AND.L D6,D3 ;MASK PATTERN DATA
AND.L (A2)+,D3 ;GET MASKED, CLIPPED SRC
MOVE.L D3,D0 ;COPY MASKED, CLIPPED SRC
AND.L D5,D0 ;APPLY BK TO SRC
NOT.L D3 ;GET NOT MASKED, CLIPPED SRC
AND.L (A1),D3 ;PUNCH OUT DST DATA
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;PUT RESULT TO DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
slMASK11
BGT NEXT11 ;LOOP FOR ALL LONGS IN ROW
BEQ END11 ;DO LAST LONG WITH MASK
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 8 OR 12: BIG PATTERN --> DST
;
slXMASK8big
MOVE D7,-(SP) ;SAVE WORK REGISTER
MOVE PATHMASK(A6),D7 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D7,D6 ;MASK INDEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
TST D2
BRA.S XDO8
XEND8 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
XNEXT8 MOVE.L 0(A3,D6),D0 ;GET PATTERN DATA
ADDQ #4,D6 ;BUMP PATTERN INDEX
AND D7,D6 ;MASK INDEX INTO PATTERN
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
AND.L D3,D0 ;MASK PATTERN DATA
NOT.L D3 ;MAKE NOTMASK
AND.L (A1),D3 ;AND NOTMASK WITH OLD DST
OR.L D0,D3 ;FILL HOLE WITH PATTERN
MOVE.L D3,(A1)+ ;UPDATE DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
XDO8 BGT XNEXT8 ;LOOP FOR ALL LONGS IN ROW
BEQ XEND8 ;DO LAST LONG WITH MASK
MOVE (SP)+,D7 ;RESTORE WORK REGISTER
RTS
;******************************************************************************************
; QuickerDraw
; Scan line handler for clipped pattern fill copy mode (called by oval, rrect)
; for complex patterns-- trap $384
; this has fixes exactly as shown in QDciPatchROM.a <sm 6/9/92>stb
FillClipXLine
slXMASK8
CMP.W #4,PATHMASK(A6) ;pattern too complex?
BGT.S slXMASK8big ;if so, don't handle
MOVE.L D7,-(SP) ;save work register
; keep the pattern in D6 and D7
ADD.W PATHPOS(A6),D0
AND #4,D0
MOVE.L EXPAT(A6),A0
ADD.l PATVPOS(A6),A0 ; <BAL 07Nov89>
MOVE.L 0(A0,D0),D6 ;get left pattern
EOR.W #4,D0
MOVE.L 0(A0,D0),D7 ;get right pattern
; fetch the leftmost region mask
MOVEQ #-1,D4 ;all ones for comparing
AND.L (A2)+,D3 ;use left mask to start with
SUBQ #1,D2
BMI.S DoFCXLast0
; special case the left edge
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
EXG.L D6,D7
MOVE.L (A2)+,D3
SUBQ #1,D2
BMI.S DoFCXLast0
; see if we're in the unclipped case; if so, use a faster loop
MOVE.L SEEKMASK(A6),A0 ;get seekRgn address
; CMP.W #$4E75,(A0) ;is it a RTS?
CMP.L #$343C7fff,(A0) ;is it "move.w #$7fff,d2"
BEQ.S DoFCXUnclipped ;if so, handle specially
BRA.S FCXNotOn1
; here's the loop -- use standard technique of special casing region masks
FCXLineLoop
MOVE.L (A2)+,D3 ;fetch region mask
BEQ.S FCXOff ;if all zero, can optimize
FCXNotOff1
CMP.L D4,D3 ;all ones?
BEQ.S FCXOn ;if so, optimize
FCXNotOn1
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
EXG.L D6,D7
DBRA D2,FCXLineLoop
; handle the last one, using the mask in D1
DoFCXLast
MOVE.L (A2)+,D3
DoFCXLast0
AND.L D1,D3 ;use right mask
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
MOVE.L (SP)+,D7 ;restore work reg
RTS
; handle the case of an all zero region mask
FCXOff
ADDQ #4,A1 ;skip over it
EXG.L D6,D7 ;exchange pattern parts even if skipping <SMC 17Oct90> <16>
SUBQ #1,D2
BMI.S DoFCXLast
FCXOffLoop
MOVE.L (A2)+,D3
BNE.S FCXNotOff1
ADDQ #4,A1 ;skip it
EXG.L D6,D7 ;exchange pattern parts even if skipping <SMC 17Oct90> <16>
DBRA D2,FCXOffLoop
BRA.S DoFCXLast
; handle the case of an all one's region mask
FCXOn
MOVE.L D6,(A1)+
EXG.L D6,D7
SUBQ #1,D2
BMI.S DoFCXLast
FCXOnLoop
MOVE.L (A2)+,D3
CMP.L D4,D3
BNE.S FCXNotOn1
MOVE.L D6,(A1)+
EXG.L D6,D7
DBRA D2,FCXOnLoop
BRA.S DoFCXLast
; handle the unclipped case with faster unwound code
DoFCXUnclipped
LEA 0(A2,D2.W*4),A2 ;bump region ptr
ADDQ #1,D2 ;compute count to do
CMP.W #8,D2
BLT.S FinishFCXUnClip
MOVE.W D2,D0
LSR #3,D0 ;divide by 8
SUBQ #1,D0 ;bias for DBRA
FCXUnClipLoop
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
DBRA D0,FCXUnClipLoop
; now finish up the last 7 or less
FinishFCXUnClip
AND #7,D2
EOR #7,D2
BTST #0,D2
BEQ.S @0
EXG.L D6,D7
@0
JMP FinishFCXUCTab(D2.W*2)
FinishFCXUCTab
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
EXG.L D6,D7
BRA DoFCXLast
;******************************************************************************************
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 9 OR 13: BIG PATTERN OR DST --> DST
;
slXMASK9
MOVE D7,-(SP) ;SAVE WORK REGISTER
MOVE PATHMASK(A6),D7 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D7,D6 ;MASK INTEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S XDO9 ;AND JUMP INTO LOOP
XEND9 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
XNEXT9 AND.L 0(A3,D6),D3 ;MASK PATTERN DATA
ADDQ #4,D6 ;BUMP INDEX INTO PATTERN
AND D7,D6 ;MASK INDEX INTO PATTERN
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
MOVE.L D3,D0 ;COPY MASKED, CLIPPED SRC
AND.L D4,D0 ;APPLY FG COLOR TO SRC
NOT.L D3 ;GET NOT MASKED, CLIPPED SRC
AND.L (A1),D3 ;USE TO PUNCH OUT DST
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;MOVE RESULT INTO DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
XDO9 BGT XNEXT9 ;LOOP FOR ALL LONGS IN ROW
BEQ XEND9 ;DO LAST LONG WITH MASK
MOVE (SP)+,D7 ;RESTORE WORK REGISTER
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 10 OR 14: BIG PATTERN XOR DST --> DST
;
slXMASK10
MOVE D7,-(SP) ;SAVE WORK REGISTER
MOVE PATHMASK(A6),D7 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D7,D6 ;MASK INDEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S XDO10 ;AND JUMP INTO LOOP
XEND10 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
XNEXT10 AND.L 0(A3,D6),D3 ;MASK PATTERN DATA
ADDQ #4,D6 ;BUMP INDEX INTO PATTERN
AND D7,D6 ;MASK INDEX INTO PATTERN
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
EOR.L D3,(A1)+ ;XOR RESULT INTO DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
XDO10 BGT XNEXT10 ;LOOP FOR ALL LONGS IN ROW
BEQ XEND10 ;DO LAST LONG WITH MASK
MOVE (SP)+,D7 ;RESTORE WORK REGISTER
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 11 OR 15: BIG PATTERN BIC DST --> DST
;
slXMASK11
MOVE D7,-(SP) ;SAVE WORK REGISTER
MOVE PATHMASK(A6),D7 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D7,D6 ;MASK INDEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S XDO11 ;AND JUMP INTO LOOP
XEND11 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
XNEXT11 AND.L 0(A3,D6),D3 ;MASK PATTERN DATA
ADDQ #4,D6 ;BUMP INDEX INTO PATTERN
AND D7,D6 ;MASK INDEX INTO PATTERN
AND.L (A2)+,D3 ;GET MASKED, CLIPPED SRC
MOVE.L D3,D0 ;COPY MASKED, CLIPPED SRC
AND.L D5,D0 ;APPLY BK TO SRC
NOT.L D3 ;GET NOT MASKED, CLIPPED SRC
AND.L (A1),D3 ;PUNCH OUT DST DATA
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;PUT RESULT TO DST
MOVEQ #-1,D3 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
XDO11 BGT XNEXT11 ;LOOP FOR ALL LONGS IN ROW
BEQ XEND11 ;DO LAST LONG WITH MASK
MOVE (SP)+,D7 ;RESTORE WORK REGISTER
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 42: PAT + DST --> DST (no pin)
; D4 is destination offset rather than foreground color
; D5 is inverse table size rather than background color
slAddOver
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR.S arithSetup ;set up registers for slab bit blt
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
LEA red(A0,D0*8),A4 ;figure out where it lives in the color table
BFEXTU (A1){D4:D7},D0 ;a pixel of the destination
LEA red(A0,D0*8),A5 ;figure out where destination lives
MOVE (A4)+,D0 ;red get source color value
ADD (A5)+,D0 ; combine source and destination
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;green get source color value
ADD (A5)+,D0 ; combine source and destination
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;blue get source color value
ADD (A5)+,D0 ; combine source and destination
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ;r, g, b in high word
MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Utility arithSetup
; sets up registers for arithmetic modes:
;
; A0 = base offset in bits (left * pixelSize)
;
; D4 = 0 (destination bit offset) D5 = inverse color table resolution
; D6 = source bit offset D7 = bits per pixel
; A0 = color table pointer A3 = source pointer
;
arithSetup
MOVEQ #0,D4 ;start off dest. at 0
MOVE invSize(A6),D5 ;set up resolution of inverse color table
MOVEQ #0,D6 ;start with left side of pattern
MOVEQ #0,D7 ;zero high word
MOVE dstPix+pixelSize(A6),D7 ;set up pixel size
MOVE.L A0,A3 ;set up pointer to pat long in case pattern is small
CMP #4,patRow(A6) ;big pat?
BLE.S @skipBig
move.l slabLeft(a6),d6 ;get bit offset into src <BAL 17Jan89>
and.l #~$1f,d6 ;truncate to long boundary <BAL 18Jan89>
move.w patHPos(a6),a0 ;make into a long <BAL 17Jan89>
add.l a0,D6 ;compute src offset in d6 <BAL 17Jan89>
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
@skipBig
SUB.L D7,D6 ;less 1 since bumped before used
MOVE.L colorTable(A6),A0 ;set up pointer to color table
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 41: PAT + DST --> DST (pin to max)
; D4 is destination offset rather than foreground color
; D5 is inverse table size rather than background color
slAddPin
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR.S arithSetup ;set up registers for slab bitblt
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
LEA red(A0,D0*8),A4 ;figure out where it lives in the color table
BFEXTU (A1){D4:D7},D0 ;a pixel of the destination
LEA red(A0,D0*8),A5 ;figure out where destination lives
MOVE (A4)+,D0 ;red get source color value
ADD (A5)+,D0 ; combine source and destination
BCS.S @tooBigRed
CMP pin+4(A6),D0 ;bigger than pin value?
BLS.S @notTooBigRed ;no, no problem
@tooBigRed
MOVE pin+4(A6),D0
@notTooBigRed
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;green get source color value
ADD (A5)+,D0 ; combine source and destination
BCS.S @tooBigGreen
CMP pin+2(A6),D0 ;bigger than pin value?
BLS.S @notTooBigGreen ;no, no problem
@tooBigGreen
MOVE pin+2(A6),D0
@notTooBigGreen
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;blue get source color value
ADD (A5)+,D0 ; combine source and destination
BCS.S @tooBigBlue
CMP pin(A6),D0 ;bigger than pin value?
BLS.S @notTooBigBlue ;no, no problem
@tooBigBlue
MOVE pin(A6),D0
@notTooBigBlue
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ;r, g, b in high word
MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 46: DST - PAT --> DST (no pin)
; D4 is destination offset rather than foreground color
; D5 is inverse table size rather than background color
slSubOver
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR arithSetup ;set up registers for slab bitblt
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
LEA red(A0,D0*8),A4 ;figure out where it lives in the color table
BFEXTU (A1){D4:D7},D0 ;a pixel of the destination
LEA red(A0,D0*8),A5 ;figure out where destination lives
MOVE (A5)+,D0 ;red get source color value
SUB (A4)+,D0 ; combine source and destination
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A5)+,D0 ;green get source color value
SUB (A4)+,D0 ; combine source and destination
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A5)+,D0 ;blue get source color value
SUB (A4)+,D0 ; combine source and destination
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ;r, g, b in high word
MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 43: DST - PAT --> DST (pin to min)
; D4 is destination offset rather than foreground color
; D5 is inverse table size rather than background color
slSubPin
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR arithSetup ;set up registers for slab bitblt
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
LEA red(A0,D0*8),A4 ;figure out where it lives in the color table
BFEXTU (A1){D4:D7},D0 ;a pixel of the destination
LEA red(A0,D0*8),A5 ;figure out where destination lives
MOVE (A5)+,D0 ;red get destination color value
SUB (A4)+,D0 ; less source color
BCS.S @tooBigRed
CMP pin+4(A6),D0 ;bigger than pin value?
BHS.S @notTooBigRed ;no, no problem
@tooBigRed
MOVE pin+4(A6),D0
@notTooBigRed
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A5)+,D0 ;green get destination color value
SUB (A4)+,D0 ; less source color
BCS.S @tooBigGreen
CMP pin+2(A6),D0 ;bigger than pin value?
BHS.S @notTooBigGreen ;no, no problem
@tooBigGreen
MOVE pin+2(A6),D0
@notTooBigGreen
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A5)+,D0 ;blue get destination color value
SUB (A4)+,D0 ; less source color
BCS.S @tooBigBlue
CMP pin(A6),D0 ;bigger than pin value?
BHS.S @notTooBigBlue ;no, no problem
@tooBigBlue
MOVE pin(A6),D0
@notTooBigBlue
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ;r, g, b in high word
MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 45: MAX(PAT, DST) --> DST
;
slMax
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR arithSetup ;set up registers for slab bitblt
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
LEA red(A0,D0*8),A4 ;figure out where it lives in the color table
BFEXTU (A1){D4:D7},D0 ;a pixel of the destination
LEA red(A0,D0*8),A5 ;figure out where destination lives
MOVE (A4)+,D0 ;Red get pattern color value
CMP (A5),D0 ; compare with destination color
BHS.S @gotTheMaxRed ; if pattern is larger, use pattern
MOVE (A5),D0 ; if destination is larger, use destination
@gotTheMaxRed
ADDQ #2,A5 ; advance to next color
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;Blue get pattern color value
CMP (A5),D0 ; compare with destination color
BHS.S @gotTheMaxBlue ; if pattern is larger, use pattern
MOVE (A5),D0 ; if destination is larger, use destination
@gotTheMaxBlue
ADDQ #2,A5 ; advance to next color
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;Green get pattern color value
CMP (A5),D0 ; compare with destination color
BHS.S @gotTheMaxGreen ; if pattern is larger, use pattern
MOVE (A5),D0 ; if destination is larger, use destination
@gotTheMaxGreen
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ;r, g, b in high word
MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 47: MIN(PAT, DST) --> DST
;
slMin
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR arithSetup ;set up registers for slab bitblt
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
LEA red(A0,D0*8),A4 ;figure out where it lives in the color table
BFEXTU (A1){D4:D7},D0 ;a pixel of the destination
LEA red(A0,D0*8),A5 ;figure out where destination lives
MOVE (A4)+,D0 ;Red get pattern color value
CMP (A5),D0 ; compare with destination color
BLS.S @gotTheMinRed ; if pattern is larger, use pattern
MOVE (A5),D0 ; if destination is larger, use destination
@gotTheMinRed
ADDQ #2,A5 ; advance to next color
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;Blue get pattern color value
CMP (A5),D0 ; compare with destination color
BLS.S @gotTheMinBlue ; if pattern is larger, use pattern
MOVE (A5),D0 ; if destination is larger, use destination
@gotTheMinBlue
ADDQ #2,A5 ; advance to next color
ASL.L D5,D0 ; save the top bits in the top word
MOVE (A4)+,D0 ;Green get pattern color value
CMP (A5),D0 ; compare with destination color
BLS.S @gotTheMinGreen ; if pattern is larger, use pattern
MOVE (A5),D0 ; if destination is larger, use destination
@gotTheMinGreen
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ;r, g, b in high word
MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 40: AVG(SRC, DST, WEIGHT) --> DST
slAvg
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
MOVE.L D1,-(SP) ;free up register
BSR arithSetup ;set up registers for slab bitblt
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA @loopEnd
@loopRight
AND.L (SP)+,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
LEA red(A0,D0*8),A4 ;figure out where it lives in the color table
BFEXTU (A1){D4:D7},D0 ;a pixel of the destination
LEA red(A0,D0*8),A5 ;figure out where destination lives
MOVE (A4)+,D0 ;red get source color value
MULU weight+4(A6),D0 ; weight varies from 0 to 1
MOVE (A5)+,D1 ; get destination
MULU notWeight+4(A6),D1 ; weight varies from 1 to 0
ADD.L D1,D0 ; combine them
CLR D0 ; clear low word
SWAP D0 ; high word is interesting part
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ; and toss remaining bits
ASL D5,D0 ; move to the green position
ASL D5,D0 ; move to the red position
MOVE D0,-(SP) ; save it
MOVE (A4)+,D0 ;green get source color value
MULU weight+2(A6),D0 ; weight varies from 0 to 1
MOVE (A5)+,D1 ; get destination
MULU notWeight+2(A6),D1 ; weight varies from 1 to 0
ADD.L D1,D0 ; combine them
CLR D0 ; clear low word
SWAP D0 ; high word is interesting part
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ; and toss remaining bits
ASL D5,D0 ; move to the green position
OR D0,(SP) ;combine with the red bits
MOVE (A4)+,D0 ;blue get source color value
MULU weight(A6),D0 ; weight varies from 0 to 1
MOVE (A5)+,D1 ; get destination
MULU notWeight(A6),D1 ; weight varies from 1 to 0
ADD.L D1,D0 ; combine them
CLR D0 ; clear low word
SWAP D0 ; high word is interesting part
ASL.L D5,D0 ; save the top bits in the top word
SWAP D0 ; and toss remaining bits
OR (SP)+,D0 ;add in the red and green
MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 58: (pat as mask) background color <--> hilite color
;
;
; Note that a fast case could be implemented (like in rgnblt, bitblt) if the pattern source
; was known to be black.
;
; Contains the fix from QDciPatchROM.a
slHilite
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR arithSetup ;set up registers for slab bitblt
BFEXTU transColor(A6){0:D7},D5 ;get a pixel of the background color
BFEXTU hilitColor(A6){0:D7},D0 ;get a pixel of the hilite color
MOVE.L D0,A0 ;save the hilite color pixel in a free register
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
CMP.L D5,D0 ; <¥¥¥>
BEQ.S @skip
BFEXTU (A1){D4:D7},D0 ;get a pixel of the destination
CMP.L D5,D0 ;same as the background color?
BNE.S @tryNew
MOVE.L A0,D0 ;put hilite color in data register
BFINS D0,(A1){D4:D7} ;move hilite color to destination
BRA.S @skip
@tryNew
CMP.L A0,D0 ;same as new color?
BNE.S @skip
BFINS D5,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 44: PAT less bg --> DST
; Note that unlike the BitBlt and RgnBlt cases, this has no optimization for when a
; long of the pattern equals the background. The optimizations in BitBlt and RgnBlt
; are intended to allow sources other than patterns to be quickly masked and blitted.
slTransparent
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
BSR arithSetup ;set up registers for slab bitblt
BFEXTU transColor(A6){0:D7},D5 ;get a pixel of the transparent color
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
CMP.l D5,D0 ;same as the background? <BAL 17Jan89>
BEQ.S @skip
BFINS D0,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havenÕt finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
ALIGN Alignment
;--------------------------------------------------------------------------
;
;
; Here begins the arithmetic transfer loops for 32 bits/pixel:
;
;
;
;--------------------------------------------------------------------------
;
; MODE 42: PAT + DST --> DST (no pin)
;-------------------------------------------------------
; a0 = hi bit mask d0 = hi bit clring mask
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = src msb's
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = dst msb's
;-------------------------------------------------------
slAddOver32
move.l d7,-(sp) ;preserve d7
BSR arithSetup32 ;set up registers for slab bitblt
move.l #~$ff808080,d0 ;get high bit clearing mask
move.l #$00808080,a0 ;get high bit mask
@blit tst.l (a2)+ ;a pixel of the clip region
beq.s @skip
move.l 0(a3,d6),d1 ;get src pixel
move.l a0,d7 ;copy high bit mask
and.l d1,d7 ;remember src msb's
and.l d0,d1 ;mask out stragglers
move.l (a1),d5 ;get dest pixel
move.l a0,d3 ;copy high bit mask
and.l d5,d3 ;remember dst msb's
and.l d0,d5 ;mask out stragglers
add.l d1,d5 ;merge src with dst
eor.l d7,d3 ;compute partial sum of msb's
eor.l d3,d5 ;compute partial sum of msb's
MOVE.L d5,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Utility arithSetup
; sets up registers for 32 bit arithmetic modes:
;
;
; INPUTS: A1: DSTPTR
; A2: MASKPTR
; D1: RIGHTMASK
; D2: LONGCNT
; D3: LEFTMASK
; D4: FGCOLOR
; D5: BKCOLOR
; D6: PATTERN
;
; CLOBBERS: D0,D3,D2,A1,A2
; A3,D6 (BUT NOT IN FASTSLAB)
arithSetup32
subq #1,d2 ;make zero based
MOVE PATHMASK(A6),D4 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D4,D6 ;MASK INDEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 41: PAT + DST --> DST (pin to max)
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = lo3Bytes mask
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = pin pixel 0rgb
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = src pixel
;-------------------------------------------------------
slAddPin32
move.l d7,a0 ;save d7 in a0
BSR arithSetup32 ;set up registers for slab bitblt
;set up pin pixel as 0rgb in D3
moveq #0,d3 ;start fresh, waste iTabRes
move.b pin+4(a6),d3 ;pick up red
swap d3 ;put in byte 3
move.w pin+2(a6),d3 ;get green in byte 2
move.b pin(a6),d3 ;put blue in lo byte
move.l Lo3Bytes,d1 ;pick up mask
@blit tst.l (a2)+ ;a pixel of the clip region
beq.s @skip
move.l 0(a3,d6),d7 ;get src pixel
and.l d1,d7 ;waste high byte
move.l d7,d0 ;make a copy of the src xrgb
move.l (a1),d5 ;get dest pixel
and.l d1,d5 ;waste high byte
clr.b d0 ;prevent carries from below
add.w d5,d0 ;add green components
BCS.S @PinGreen
cmp.w d3,d0 ;do we need to pin result?
bls.s @GreenOK
@PinGreen
move.w d3,d0 ;use pin value instead
@GreenOK
move.b d7,d0 ;get src blue
add.b d5,d0 ;add dest blue
BCS.S @PinBlue
cmp.b d3,d0 ;do we need to pin result?
bls.s @BlueOK
@PinBlue
move.b d3,d0 ;use pin value instead
@BlueOK
clr.w d5 ;now d5 has only red in byte 3
add.l d5,d0 ;add red components
cmp.l d3,d0 ;compare red components
bls.s @RedOK
@PinRed
swap d3 ;get max red in lo word
swap d0 ;get too big red in lo word
move.w d3,d0 ;pin to max red
swap d0 ;get back 0rgb
swap d3 ;restore pin pixel
@RedOK
MOVE.L d0,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l a0,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 46: DST - PAT --> DST (no pin)
;
;-------------------------------------------------------
; a0 = d0 = hi bit clring mask
; a1 = dstPtr d1 = high bit mask
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = src msb's
; a4 = d4 = dst msb's
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = src pixel
;-------------------------------------------------------
slSubOver32
move.l d7,a0 ;save d7 in a0
BSR arithSetup32 ;set up registers for slab bitblt
move.l #~$ff808080,d0 ;get high bit clearing mask
move.l #$00808080,d1 ;get high bit mask
@blit tst.l (a2)+ ;a pixel of the clip region
beq.s @skip
move.l 0(a3,d6),d7 ;get src pixel
move.l d1,d3 ;copy high bit mask
and.l d7,d3 ;remember src msb's
eor.l d1,d3 ;invert src msb's
and.l d0,d7 ;mask out stragglers
move.l (a1),d5 ;get dest pixel
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,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l a0,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 43: DST - PAT --> DST (pin to min)
;
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = lo3Bytes mask
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = pin pixel 0rgb
; a4 = d4 = patHMask
; a5 = d5 = src pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = dst pixel
;-------------------------------------------------------
slSubPin32
move.l d7,a0 ;save d7 in a0
BSR arithSetup32 ;set up registers for slab bitblt
;set up pin pixel as 0rgb in D3
moveq #0,d3 ;start fresh, waste iTabRes
move.b pin+4(a6),d3 ;pick up red
swap d3 ;put in byte 3
move.w pin+2(a6),d3 ;get green in byte 2
move.b pin(a6),d3 ;put blue in lo byte
move.l Lo3Bytes,d1 ;pick up mask
@blit tst.l (a2)+ ;a pixel of the clip region
beq.s @skip
move.l 0(a3,d6),d5 ;get src pixel
and.l d1,d5 ;waste high byte
move.l (a1),d7 ;get dest pixel
and.l d1,d7 ;waste high byte
move.l d7,d0 ;make a copy of the dst xrgb
st d0 ;prevent borrows from below
sub.w d5,d0 ;sub green components
BCS.S @PinGreen
cmp.w d3,d0 ;do we need to pin result?
bhs.s @GreenOK
@PinGreen
move.w d3,d0 ;use pin value instead
@GreenOK
move.b d7,d0 ;get dest blue
sub.b d5,d0 ;sub src blue
BCS.S @PinBlue
cmp.b d3,d0 ;do we need to pin result?
bhs.s @BlueOK
@PinBlue
move.b d3,d0 ;use pin value instead
@BlueOK
clr.w d5 ;now d5 has only red in byte 3
sub.l d5,d0 ;sub red components
cmp.l d3,d0 ;compare red components
bge.s @RedOK
@PinRed
swap d3 ;get max red in lo word
swap d0 ;get too big red in lo word
move.w d3,d0 ;pin to max red
swap d0 ;get back 0rgb
swap d3 ;restore pin pixel
@RedOK
MOVE.L d0,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l a0,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 45: MAX(PAT, DST) --> DST
;
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 =
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
slMax32
BSR arithSetup32 ;set up registers for slab bitblt
@blit tst.l (a2)+ ;a pixel of the clip region
beq.s @skip
move.l 0(a3,d6),d1 ;get src pixel
move.l (a1),d5 ;get dest pixel
move.l d5,d0 ;make a copy of the dest xrgb
cmp.w d1,d0 ;compare g,b components
BHI.S @gotMaxGreen
move.w d1,d0 ;keep the bigger of the two
move.b d5,d0 ;prime for blue
@gotMaxGreen
cmp.b d1,d5 ;compare blue components
BHI.S @gotMaxBlue
move.b d1,d0 ;keep the bigger of the two
@gotMaxBlue
swap d1
swap d0
cmp.b d1,d0 ;compare red components
BHI.S @gotMaxRed
move.b d1,d0 ;keep the bigger of the two
@gotMaxRed
swap d0 ;get new xrgb
MOVE.L d0,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 47: MIN(PAT, DST) --> DST
;
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 =
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
slMin32
BSR arithSetup32 ;set up registers for slab bitblt
@blit tst.l (a2)+ ;a pixel of the clip region
beq.s @skip
move.l 0(a3,d6),d1 ;get src pixel
move.l (a1),d5 ;get dest pixel
move.l d5,d0 ;make a copy of the dest xrgb
cmp.w d1,d0 ;compare g,b components
BLS.S @gotMinGreen
move.w d1,d0 ;keep the smaller of the two
move.b d5,d0 ;prime for blue
@gotMinGreen
cmp.b d1,d5 ;compare blue components
BLS.S @gotMinBlue
move.b d1,d0 ;keep the smaller of the two
@gotMinBlue
swap d1
swap d0
cmp.b d1,d0 ;compare red components
BLS.S @gotMinRed
move.b d1,d0 ;keep the smaller of the two
@gotMinRed
swap d0 ;get new xrgb
MOVE.L d0,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 40: AVG(SRC, DST, WEIGHT) --> DST
;
; CLOBBERS: D0,D3,D2,A1,A2
; A3,D6 (BUT NOT IN FASTSLAB)
;-------------------------------------------------------
; a0 = /last dst d0 = red weight
; a1 = dstPtr d1 = blue/grn weight (scanCount)
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = /last src
; a4 = d4 = /last result
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = src pixel
;-------------------------------------------------------
slAvg32
lea @slAvg32Slow,a4 ;assume, general blend32 from now on
lea weight(a6),a0 ;point to weights
move.w (a0)+,d3
cmp.w (a0)+,d3 ;is opColor gray?
bne.s @slAvg32Slow
cmp.w (a0),d3
bne.s @slAvg32Slow
addq #1,d3 ;yes, check for gray values of $8000 or $7fff
and.w #$fffe,d3
cmp.w #$8000,d3
bne.s @slAvg32Slow
lea @slAvg32Half,a4 ;use fast 50% blend32 from now on
bra @slAvg32Half
ALIGN Alignment
;-------------------------------------------------------
;
; General blend case for non 50% gray weights
;
;
@slAvg32Slow
MOVE.L D7,-(SP) ;preserve extra registers
BSR arithSetup32 ;set up registers for slab bitblt
lea weight(a6),a0 ;point at blue weight
move.l (a0)+,d1 ;get blue/green weight
move.w (a0),d0 ;get red weight
@short0 moveq #0,d4 ;init last result
move.l d4,d3 ;init last src
move.l d4,a0 ;init last dst
@blit tst.l (A2)+ ;a pixel of the clip region
BEQ.S @skip
move.l 0(a3,d6),d7 ;get src pixel
move.l (a1),d5 ;get dest pixel
@short1 cmp.l d3,d7 ;same as last time?
bne.s @blue ;no, go do it
cmp.l a0,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,a0 ;a0 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,a0 ;a0 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 a0,d4 ;d4 has 0RGB
@short2 swap d5 ;get back dst
move.l d5,a0 ;save for short circuit
swap d7 ;get back src
move.l d7,d3 ;save for short circuit
@again MOVE.L d4,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
MOVE.L (SP)+,D7 ;restore regs
RTS
ALIGN Alignment
;--------------------------------------------
;
; Optimized 50% blend case for 32 bits/pixel
;
;-------------------------------------------------------
; a0 = low bit mask d0 = high bit mask
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = lsb's of result
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
@slAvg32Half
BSR arithSetup32 ;set up registers for slab bitblt
move.l #~$ff808080,d0 ;get high bit mask
move.l #$10101,a0 ;get low bit mask
@blit2 tst.l (A2)+ ;a pixel of the clip region
BEQ.S @skip2
move.l 0(a3,d6),d1 ;get src pixel
move.l a0,d3 ;copy low bit mask
and.l d1,d3 ;remember src lsb's
lsr.l #1,d1 ;get almost 1/2 of it
and.l d0,d1 ;mask out stragglers
move.l (a1),d5 ;get dest pixel
and.l d5,d3 ;compute carry out of lsb
lsr.l #1,d5 ;get almost 1/2 of it
and.l d0,d5 ;mask out stragglers
add.l d5,d1 ;merge src with dst
add.l d3,d1 ;propagate carrys
MOVE.L d1,(a1) ;write pattern to dest
@skip2 addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit2 ;LOOP ALL LONGS THIS ROW
RTS
ALIGN Alignment
;--------------------------------------------
;
; Mode: 36 Transparent for 32 bits/pixel
;
;-------------------------------------------------------
; a0 = d0 =
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 =
; a4 = d4 = patHMask
; a5 = d5 = backColor
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
slTransparent32
BSR arithSetup32 ;set up registers for slab bitblt
move.l transColor(A6),D5 ;get a pixel of the transparent color
@blit tst.l (A2)+ ;a pixel of the clip region
BEQ.S @skip
move.l 0(a3,d6),d1 ;get src pixel
cmp.l d1,d5 ;is src backColor?
beq.s @skip ;yes, don't write to dst
MOVE.L d1,(a1) ;write pattern to dest
@skip addq.l #4,a1 ;bump dst ptr
addq.l #4,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
RTS
ALIGN Alignment
;--------------------------------------------------------------------------
;
;
; Here begin the arithmetic transfer loops for 16 bits/pixel:
;
;
;
;--------------------------------------------------------------------------
;
; MODE 42: PAT + DST --> DST (no pin)
;-------------------------------------------------------
; a0 = hi bit mask d0 = hi bit clring mask
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = src msb's
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = dst msb's
;-------------------------------------------------------
slAddOver16
move.l d7,-(sp) ;preserve d7
BSR.s arithSetup16 ;set up registers for slab bitblt
move.w #$3def,d0 ;get high bit clearing mask
move.w #$4210,a0 ;get high bit mask
@blit tst.w (a2)+ ;a pixel of the clip region
beq.s @skip
move.w 0(a3,d6),d1 ;get src pixel
move.w a0,d7 ;copy high bit mask
and.w d1,d7 ;remember src msb's
and.w d0,d1 ;mask out stragglers
move.w (a1),d5 ;get dest pixel
move.w a0,d3 ;copy high bit mask
and.w d5,d3 ;remember dst msb's
and.w d0,d5 ;mask out stragglers
add.w d1,d5 ;merge src with dst
eor.w d7,d3 ;compute partial sum of msb's
eor.w d3,d5 ;compute partial sum of msb's
MOVE.w d5,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Utility arithSetup
; sets up registers for 16 bit arithmetic modes:
;
; INPUT
; REGISTERS: A0: D0: CLOBBERED ;
; A1: DSTPTR D1: CLOBBERED ;
; A2: MASKPTR D2: LONGCNT ;
; A3: SRCPTR D3: FGCOLOR ;
; A4: modecase D4: BKCOLOR ;
; A5: D5: CLOBBERED ;
; A6: D6: DSTALIGN ;
; A7: D7: PixelSize ;
; ;
arithSetup16
asl.w #1,d2 ;2 pixels per long
beq.s @oneLong
subq #1,d2 ;make zero based
neg d1 ;convert mask to extra pixel cnt
add d1,d2 ;include right pixel of last long
swap d1
neg d1 ;convert mask to extra pixel cnt
add d1,d2 ;include right pixel of last long
@noRight
tst.l d3 ;worry about first pixel?
bmi.s @noLeft ;yes, do it!
subq #1,d2 ;shorten count
@skipLeft
addq #2,a2 ;bump mask past first pixel
addq #2,a3 ;bump src past first pixel
addq #2,a1 ;bump dst past first pixel
addq #2,d0 ;bump pat index*
@noLeft
MOVE PATHMASK(A6),D4 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D4,D6 ;MASK INDEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
RTS
@oneLong
and.l d1,d3 ;combine left and right mask
bpl.s @skipLeft ;skip first pixel
neg.w d3 ;turn right pixel in to bump
add.w d3,d2 ;conditionally bump count
bra.s @noLeft
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 41: PAT + DST --> DST (pin to max)
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = lo3Bytes mask
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = pin pixel 0rgb
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = src pixel
;-------------------------------------------------------
slAddPin16
move.l d7,-(sp) ;preserve d7
BSR.s arithSetup16 ;set up registers for slab bitblt
;set up pin pixel as 0rgb in D3
moveq #0,d3 ;start fresh, waste iTabRes
move.b pin+4(a6),d3 ;pick up red
lsr.b #3,d3 ;get right aligned 5 bits
swap d3 ;put in byte 3
move.w pin+2(a6),d3 ;get green in byte 2
lsr.w #3,d3 ;get right aligned 5 bits
move.b pin(a6),d3 ;put blue in lo byte
lsr.b #3,d3 ;right flush blue
@blit tst.w (a2)+ ;a pixel of the clip region
beq.s @skip
moveq #0,d7
move.w 0(a3,d6),d7 ;get src pixel
add.w d7,d7 ;waste high bit
lsl.l #5,d7 ;but red in byte 3
lsr.w #3,d7 ;but green in byte 2, blue in lo byte
lsr.b #3,d7 ;right flush blue
moveq #0,d5
move.w (a1),d5 ;get dest pixel
add.w d5,d5 ;waste high bit
lsl.l #5,d5 ;but red in byte 3
lsr.w #3,d5 ;but green in byte 2, blue in lo byte
lsr.b #3,d5 ;right flush blue
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,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 46: DST - PAT --> DST (no pin)
;
;-------------------------------------------------------
; a0 = d0 = hi bit clring mask
; a1 = dstPtr d1 = high bit mask
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = src msb's
; a4 = d4 = dst msb's
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = src pixel
;-------------------------------------------------------
slSubOver16
move.l d7,-(sp) ;preserve d7
BSR arithSetup16 ;set up registers for slab bitblt
move.w #$3def,d0 ;get high bit clearing mask
move.w #$4210,d1 ;get high bit mask
@blit tst.w (a2)+ ;a pixel of the clip region
beq.s @skip
move.w 0(a3,d6),d7 ;get src pixel
move.w d1,d3 ;copy high bit mask
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 (a1),d5 ;get dest pixel
move.w d1,d4 ;copy high bit mask
and.w d5,d4 ;remember dst msb's
and.w d0,d5 ;mask out high byte
or.w d1,d5 ;force high bits on
sub.w d7,d5 ;compute dst - src
eor.w d3,d4 ;compute partial sum of msb's
eor.w d4,d5 ;compute partial sum of msb's
MOVE.w d5,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 43: DST - PAT --> DST (pin to min)
;
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = lo3Bytes mask
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = pin pixel 0rgb
; a4 = d4 = patHMask
; a5 = d5 = src pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = dst pixel
;-------------------------------------------------------
slSubPin16
move.l d7,-(sp) ;preserve d7
BSR arithSetup16 ;set up registers for slab bitblt
;set up pin pixel as 0rgb in D3
moveq #0,d3 ;start fresh, waste iTabRes
move.b pin+4(a6),d3 ;pick up red
lsr.b #3,d3 ;get right aligned 5 bits
swap d3 ;put in byte 3
move.w pin+2(a6),d3 ;get green in byte 2
lsr.w #3,d3 ;get right aligned 5 bits
move.b pin(a6),d3 ;put blue in lo byte
lsr.b #3,d3 ;right flush blue
move.l #$808080,d1 ;borrow stopper
add.l d1,d3 ;prevent borrows from crossing byte boundaries
@blit tst.w (a2)+ ;a pixel of the clip region
beq.s @skip
moveq #0,d7
move.w 0(a3,d6),d7 ;get src pixel
add.w d7,d7 ;waste high bit
lsl.l #5,d7 ;but red in byte 3
lsr.w #3,d7 ;but green in byte 2, blue in lo byte
lsr.b #3,d7 ;right flush blue
moveq #0,d5
move.w (a1),d5 ;get dest pixel
add.w d5,d5 ;waste high bit
lsl.l #5,d5 ;but red in byte 3
lsr.w #3,d5 ;but green in byte 2, blue in lo byte
lsr.b #3,d5 ;right flush blue
add.l d1,d5 ;prevent borrows from crossing byte boundaries
sub.l d7,d5 ;sub all components at once
move.l d5,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 d5,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 d5,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,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 45: MAX(PAT, DST) --> DST
;
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 =
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
slMax16
move.l d7,-(sp) ;preserve d7
BSR arithSetup16 ;set up registers for slab bitblt
@blit tst.w (a2)+ ;a pixel of the clip region
beq.s @skip
moveq #0,d7
move.w 0(a3,d6),d7 ;get src pixel
add.w d7,d7 ;waste high bit
lsl.l #5,d7 ;but red in byte 3
lsr.w #3,d7 ;but green in byte 2, blue in lo byte
lsr.b #3,d7 ;right flush blue
moveq #0,d5
move.w (a1),d5 ;get dest pixel
add.w d5,d5 ;waste high bit
lsl.l #5,d5 ;but red in byte 3
lsr.w #3,d5 ;but green in byte 2, blue in lo byte
lsr.b #3,d5 ;right flush blue
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,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 47: MIN(PAT, DST) --> DST
;
;-------------------------------------------------------
; a0 = d0 = result
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 =
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
slMin16
move.l d7,-(sp) ;preserve d7
BSR arithSetup16 ;set up registers for slab bitblt
@blit tst.w (a2)+ ;a pixel of the clip region
beq.s @skip
moveq #0,d7
move.w 0(a3,d6),d7 ;get src pixel
add.w d7,d7 ;waste high bit
lsl.l #5,d7 ;but red in byte 3
lsr.w #3,d7 ;but green in byte 2, blue in lo byte
lsr.b #3,d7 ;right flush blue
moveq #0,d5
move.w (a1),d5 ;get dest pixel
add.w d5,d5 ;waste high bit
lsl.l #5,d5 ;but red in byte 3
lsr.w #3,d5 ;but green in byte 2, blue in lo byte
lsr.b #3,d5 ;right flush blue
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,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 40: AVG(SRC, DST, WEIGHT) --> DST
;
; CLOBBERS: D0,D3,D2,A1,A2
; A3,D6 (BUT NOT IN FASTSLAB)
;-------------------------------------------------------
; a0 = /last dst d0 = red weight
; a1 = dstPtr d1 = blue/grn weight (scanCount)
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = /last src
; a4 = d4 = /last result
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 = src pixel
;-------------------------------------------------------
slAvg16
lea @slAvg16Slow,a4 ;assume, general blend16 from now on
lea weight(a6),a0 ;point to weights
move.w (a0)+,d5
cmp.w (a0)+,d5 ;is opColor gray?
bne.s @slAvg16Slow
cmp.w (a0),d5
bne.s @slAvg16Slow
addq #1,d5 ;yes, check for gray values of $8000 or $7fff
and.w #$fffe,d5
cmp.w #$8000,d5
bne.s @slAvg16Slow
lea @slAvg16Half,a4 ;use fast 50% blend16 from now on
bra @slAvg16Half
ALIGN Alignment
;-------------------------------------------------------
;
; General blend case for non 50% gray weights
;
;
@slAvg16Slow
move.l d7,-(sp) ;preserve d7
BSR arithSetup16 ;set up registers for slab bitblt
lea weight(a6),a0 ;point at blue weight
move.l (a0)+,d1 ;get blue/green weight
move.w (a0),d0 ;get red weight
@short0 moveq #0,d4 ;init last result
move.l d4,d3 ;init last src
move.l d4,a0 ;init last dst
@blit tst.w (A2)+ ;a pixel of the clip region
BEQ @skip
moveq #0,d7
move.w 0(a3,d6),d7 ;get src pixel
moveq #0,d5
move.w (a1),d5 ;get dest pixel
@short1 cmp.w d3,d7 ;same as last time?
bne.s @hardway ;no, go do it
cmp.w a0,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,a0 ;a0 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,a0 ;a0 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 a0,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,a0 ;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,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
move.l (sp)+,d7 ;restore d7
RTS
ALIGN Alignment
;--------------------------------------------
;
; Optimized 50% blend case for 16 bits/pixel
;
;-------------------------------------------------------
; a0 = low bit mask d0 = high bit mask
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 = lsb's of result
; a4 = d4 = patHMask
; a5 = d5 = dest pixel
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
@slAvg16Half
BSR arithSetup16 ;set up registers for slab bitblt
move.w #$3def,d0 ;get high bit clearing mask
move.w #$0421,a0 ;get low bit mask
@blit2 tst.w (A2)+ ;a pixel of the clip region
BEQ.S @skip2
move.w 0(a3,d6),d1 ;get src pixel
move.w a0,d3 ;copy low bit mask
and.w d1,d3 ;remember src lsb's
lsr.w #1,d1 ;get almost 1/2 of it
and.w d0,d1 ;mask out stragglers
move.w (a1),d5 ;get dest pixel
and.w d5,d3 ;compute carry out of lsb
lsr.w #1,d5 ;get almost 1/2 of it
and.w d0,d5 ;mask out stragglers
add.w d5,d1 ;merge src with dst
add.w d3,d1 ;propagate carrys
MOVE.w d1,(a1) ;write pattern to dest
@skip2 addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit2 ;LOOP ALL LONGS THIS ROW
RTS
ALIGN Alignment
;--------------------------------------------
;
; Mode: 36 Transparent for 16 bits/pixel
;
;-------------------------------------------------------
; a0 = d0 =
; a1 = dstPtr d1 = src pixel
; a2 = maskPtr d2 = run cnt
; a3 = patPtr d3 =
; a4 = d4 = patHMask
; a5 = d5 = backColor
; a6 = locals d6 = pattern offset
; a7 = d7 =
;-------------------------------------------------------
slTransparent16
BSR arithSetup16 ;set up registers for slab bitblt
move.l transColor(A6),D5 ;get a pixel of the transparent color
@blit tst.w (A2)+ ;a pixel of the clip region
BEQ.S @skip
move.w 0(a3,d6),d1 ;get src pixel
cmp.w d1,d5 ;is src backColor?
beq.s @skip ;yes, don't write to dst
MOVE.w d1,(a1) ;write pattern to dest
@skip addq.l #2,a1 ;bump dst ptr
addq.l #2,d6 ;bump src index
and.w d4,d6 ;constrict to the source long if in a pattern mode
DBRA D2,@blit ;LOOP ALL LONGS THIS ROW
RTS
ALIGN Alignment
;--------------------------------------------
;
; PROCEDURE SlabMode
;
; INPUT: D2: MODE, CLOBBERED
; OUTPUT: A4: MODECASE
;
; for arithmetic modes, also set up patHMask, patHPos
;
SlabMode
AND #$37,D2 ;toss all but arithmetic, hilite bits + variant bits
BCLR #5,D2 ;arithmetic mode?
BEQ.S @clrInvBit ;if so, donÕt clear the invert bit
BCLR #4,D2 ;hilite?
BEQ.S @skipHilite ;if not, donÕt add hilite offset
MOVEQ #8,D2 ;hilite is at $20, so put ($20 / 2) - 8 here
BRA.S @2 ; <SMC 26SEP90> <12>
@skipHilite
cmp #16,dstPix+pixelSize(A6) ;dst 16,32 bits/pixel?
bge @useLoops32 ;yes, use alternate table
@2 MOVE #$1F,patHMask(A6) ;set up patHMask for 1 long for small patterns
CMP #4,PATROW(A6) ;NEED EXPANDED PATTERN?
BLE.S @1 ;if not, all ready to go
MOVEM.L D2/D3,-(SP) ;save work registers
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
MOVE patRow(A6),D2 ;get pattern row size
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
MOVE patHPos(A6),D2 ;get pattern offset <BAL 17Jan89>
ASL #3,D2 ;convert from bytes to bits <BAL 17Jan89>
MOVE D2,patHPos(A6) ;save for arith setup <BAL 17Jan89>
MOVEM.L (SP)+,D2/D3 ;restore work registers
@1
cmp #16,dstPix+pixelSize(A6) ;dst 16,32 bits/pixel? <SMC 26SEP90> <12>
bge.s @useLoops32 ;yes, use alternate table <SMC 26SEP90> <12>
ADDQ #8,D2 ;point to arithmetic modes <SMC 26SEP90> <12>
;ciPatPrep (from QDciPatchROM.a) <sm 6/9/92>stb
if Quicker then
cmp #8,dstPix+pixelSize(A6) ;dst 8 bits/pixel?
blt.s @goTable ;yes, use alternate table <sm 6/9/92>stb
subq #8,d2 ;make average mode zero based
lea slArith8Tab,A4 ;point to 8 bit arithmetic mode table
add.l 0(A4,D2*4),A4 ;GET CASE JUMP ADDRESS
RTS
else
bra.s @goTable <sm 6/9/92>stb
endif
@clrInvBit
AND #$3,D2 ;GET LO 2 BITS OF MODE, clearing bit 4 also
BNE.S @4 ;if not a copy mode, skip over this stuff <17>
TST.B alphaMode(A6) ;are drawing in alpha mode? <17>
BEQ.S @4 ;no, use normal loops <17>
LEA slMASK8A,A4 ;get address of small pat alpha copy loop <17>
CMP #4,PATROW(A6) ;large pattern? <17>
BLE.S @3 ;no, exit <17>
LEA slXMASK8A,A4 ;yes, use big pattern copy loop <17>
@3 RTS ; <17>
@4 CMP #4,PATROW(A6) ;NEED EXPANDED PATTERN?
BLE.S @goTable ;=>NO <sm 6/9/92>stb
ADDQ #4,D2 ;ELSE BUMP TO EXPANDED ROUTINES
@goTable ; <sm 6/9/92>stb
LEA SlabModeTab,A4 ;POINT TO MODE TABLE
MOVE.L 0(A4,D2*4),A4 ;GET CASE JUMP ADDRESS
RTS
@useLoops32
beq.s @useLoops16
move.l slArith32TabPtr,A4 ;POINT TO MODE TABLE
add.l 0(A4,D2*4),A4 ;GET CASE JUMP ADDRESS
RTS
@useLoops16
move.l slArith16TabPtr,A4 ;POINT TO MODE TABLE
add.l 0(A4,D2*4),A4 ;GET CASE JUMP ADDRESS
MOVE PATHMASK(A6),D2 ;GET HORIZ MASK
bset #1,d2 ;make into word mask
MOVE d2,PATHMASK(A6) ;put HORIZ MASK
RTS
IF 0 THEN
MODETAB DC.W MODETAB-MASK8
DC.W MODETAB-MASK9
DC.W MODETAB-MASK10
DC.W MODETAB-MASK11
DC.W MODETAB-XMASK8
DC.W MODETAB-XMASK9
DC.W MODETAB-XMASK10
DC.W MODETAB-XMASK11
DC.W ModeTab-Avg ;10 AVG(PAT, DST, WEIGHT) --> DST
DC.W ModeTab-AddPin ;12 PAT + DST --> DST (pin to max)
DC.W ModeTab-AddOver ;13 PAT + DST --> DST (no pin)
DC.W ModeTab-SubPin ;16 DST - PAT --> DST (pin to min)
DC.W ModeTab-Transparent ;18 PAT less bg --> DST
DC.W ModeTab-Max ;1A MAX(PAT, DST) --> DST
DC.W ModeTab-SubOver ;1C DST - PAT --> DST (no pin)
DC.W ModeTab-Min ;1E MIN(PAT, DST) --> DST
DC.W ModeTab-Hilite ;20 (pat as mask) hilite <--> background
ENDIF
Align 4
if Quicker then
IMPORT slAddOver8
IMPORT slSubOver8
IMPORT slAddPin8
IMPORT slSubPin8
IMPORT slMax8
IMPORT slMin8
IMPORT slAvg8,slTransparent8
slArith8Tab
DC.L slAvg8-slArith8Tab ;10 AVG(PAT, DST, WEIGHT) --> DST
DC.L slAddPin8-slArith8Tab ;12 PAT + DST --> DST (pin to max)
DC.L slAddOver8-slArith8Tab ;13 PAT + DST --> DST (no pin)
DC.L slSubPin8-slArith8Tab ;16 DST - PAT --> DST (pin to min)
DC.L slTransparent8-slArith8Tab ;18 PAT less bg --> DST
DC.L slMax8-slArith8Tab ;1A MAX(PAT, DST) --> DST
DC.L slSubOver8-slArith8Tab ;1C DST - PAT --> DST (no pin)
DC.L slMin8-slArith8Tab ;1E MIN(PAT, DST) --> DST
DC.L slHilite-slArith8Tab ;20 MIN(PAT, DST) --> DST
endif
slArith16Tab
DC.L slAvg16-slArith16Tab ;10 AVG(PAT, DST, WEIGHT) --> DST
DC.L slAddPin16-slArith16Tab ;12 PAT + DST --> DST (pin to max)
DC.L slAddOver16-slArith16Tab ;13 PAT + DST --> DST (no pin)
DC.L slSubPin16-slArith16Tab ;16 DST - PAT --> DST (pin to min)
DC.L slTransparent16-slArith16Tab ;18 PAT less bg --> DST
DC.L slMax16-slArith16Tab ;1A MAX(PAT, DST) --> DST
DC.L slSubOver16-slArith16Tab ;1C DST - PAT --> DST (no pin)
DC.L slMin16-slArith16Tab ;1E MIN(PAT, DST) --> DST
DC.L slHilite-slArith16Tab ;20 (pat as mask) hilite <--> background
slArith32Tab
DC.L slAvg32-slArith32Tab ;10 AVG(PAT, DST, WEIGHT) --> DST
DC.L slAddPin32-slArith32Tab ;12 PAT + DST --> DST (pin to max)
DC.L slAddOver32-slArith32Tab ;13 PAT + DST --> DST (no pin)
DC.L slSubPin32-slArith32Tab ;16 DST - PAT --> DST (pin to min)
DC.L slTransparent32-slArith32Tab ;18 PAT less bg --> DST
DC.L slMax32-slArith32Tab ;1A MAX(PAT, DST) --> DST
DC.L slSubOver32-slArith32Tab ;1C DST - PAT --> DST (no pin)
DC.L slMin32-slArith32Tab ;1E MIN(PAT, DST) --> DST
DC.L slHilite-slArith32Tab ;20 (pat as mask) hilite <--> background
ALIGN Alignment
;---------------------------------------------------------------
;
; FAST LOOPS, OPTIMIZED FOR SOLID PATTERN AND RECTANGLE CLIPPED
;
; FAST FOREGROUND SLAB:
;
FAST11 MOVE.L D5,D4 ; <sm 6/9/92>stb
TST D2 ; <sm 6/9/92>stb
FAST8 BEQ.S MERGE8 ;BR IF ALL IN ONE LONG
MOVE.L D3,D0 ;GET LEFTMASK
NOT.L D0 ;GET NOT LEFTMASK
AND.L (A1),D0 ;PUNCH OUT DST
AND.L D4,D3 ;OR FGCOLOR INTO LEFTMASK
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;AND PUT TO DST
SUB #2,D2 ;ADJUST LONGCOUNT FOR DBRA
BLT.S LAST8 ;BR IF NO UNMASKED LONGS
LOOP8 MOVE.L D4,(A1)+ ;WRITE A LONG OF FOREGROUND
DBRA D2,LOOP8 ;LOOP ALL UNMASKED LONGS
BRA.S LAST8 ;GO DO LAST LONG
MERGE8 AND.L D3,D1 ;COMBINE LEFTMASK AND RIGHTMASK
LAST8 MOVE.L D1,D0 ;GET MASK
AND.L D4,D0 ;APPLY FGCOLOR TO MASK
NOT.L D1 ;GET NOTMASK
AND.L (A1),D1 ;PUNCH OUT DST
OR.L D1,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;OR RIGHTMASK INTO DST
RTS ;AND RETURN
ALIGN Alignment
;
; FAST XOR SLAB:
;
FAST10 BEQ.S MERGE10 ;BR IF ALL IN ONE LONG
EOR.L D3,(A1)+ ;XOR LEFTMASK INTO DST
SUB #2,D2 ;ADJUST LONGCOUNT FOR DBRA
BLT.S LAST10 ;BR IF NO UNMASKED LONGS
LOOP10 NOT.L (A1)+ ;INVERT A LONG OF DST
DBRA D2,LOOP10 ;LOOP ALL UNMASKED LONGS
LAST10 EOR.L D1,(A1)+ ;XOR RIGHTMASK INTO DST
RTS ;AND RETURN
MERGE10 AND.L D3,D1 ;COMBINE LEFTMASK AND RIGHTMASK
EOR.L D1,(A1)+ ;XOR RIGHTMASK INTO DST
RTS ;AND RETURN
IF 0 THEN ;¥¥¥
ALIGN Alignment
; FAST BACKGROUND SLAB:
FAST11 BEQ.S MERGE11 ;BR IF ALL IN ONE LONG
MOVE.L D3,D0 ;GET LEFTMASK
NOT.L D0 ;GET NOT LEFTMASK
AND.L (A1),D0 ;PUNCH OUT DST
AND.L D5,D3 ;OR BKCOLOR INTO LEFTMASK
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;AND PUT TO DST
SUB #2,D2 ;ADJUST LONGCOUNT FOR DBRA
BLT.S LAST11 ;BR IF NO UNMASKED LONGS
LOOP11 MOVE.L D5,(A1)+ ;WRITE A LONG OF BACKGROUND
DBRA D2,LOOP11 ;LOOP ALL UNMASKED LONGS
BRA.S LAST11 ;GO DO LAST LONG
MERGE11 AND.L D3,D1 ;COMBINE LEFTMASK AND RIGHTMASK
LAST11 MOVE.L D1,D0 ;GET MASK
AND.L D5,D0 ;APPLY BKCOLOR TO MASK
NOT.L D1 ;GET NOTMASK
AND.L (A1),D1 ;PUNCH OUT DST
OR.L D1,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;OR RIGHTMASK INTO DST
RTS ;AND RETURN
ENDIF ;¥¥¥
ALIGN Alignment
; FAST FOREGROUND/BACKGROUND SLAB USING ALPHA MASK: <17>
FAST11A MOVE.L D5,D4 ;USE BKCOLOR INSTEAD OF FGCOLOR
FAST8A MOVE.L alphaMask(A6),D0 ;GET ALPHA MASK
AND.L D0,D1 ;CLIP LEFTMASK WITH ALPHAMASK
AND.L D0,D3 ;CLIP RIGHTMASK WITH ALPHAMASK
MOVE.L D0,A0 ;save copy of alpha mask
TST D2 ;RETEST THE LONG COUNT
BEQ.S MERGE8A ;BR IF ALL IN ONE LONG
MOVE.L D3,D0 ;GET LEFTMASK
NOT.L D0 ;GET NOT LEFTMASK
AND.L (A1),D0 ;PUNCH OUT DST
AND.L D4,D3 ;OR FGCOLOR INTO LEFTMASK
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;AND PUT TO DST
SUB #2,D2 ;ADJUST LONGCOUNT FOR DBRA
BLT.S LAST8A ;BR IF NO UNMASKED LONGS
MOVE.L A0,D3 ;GET CENTER MASK
NOT.L D3 ;GET NOT OF MASK
LOOP8A MOVE.L (A1),D0 ;GET THE DST
EOR.L D4,D0 ;APPLY FGCOLOR
AND.L D3,D0 ;MASK OUT PART OF DST
EOR.L D4,D0 ;REAPPLY FGCOLOR
MOVE.L D0,(A1)+ ;AND PUT TO DST
DBRA D2,LOOP8A ;LOOP ALL UNMASKED LONGS
BRA.S LAST8A ;GO DO LAST LONG
MERGE8A AND.L D3,D1 ;COMBINE LEFTMASK AND RIGHTMASK
LAST8A MOVE.L D1,D0 ;GET RIGHTMASK
NOT.L D0 ;GET NOT RIGHTMASK
AND.L (A1),D0 ;PUNCH OUT DST
AND.L D4,D1 ;OR FGCOLOR INTO RIGHTMASK
OR.L D1,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;AND PUT TO DST
RTS ;AND RETURN
ALIGN Alignment
; FAST XOR SLAB USING ALPHA MASK: <17>
FAST10A MOVE.L alphaMask(A6),D0 ;GET ALPHAMASK
AND.L D0,D1 ;CLIP LEFTMASK WITH ALPHAMASK
AND.L D0,D3 ;CLIP RIGHTMASK WITH ALPHAMASK
TST D2 ;RETEST THE LONG COUNT
BEQ.S MERGE10A ;BR IF ALL IN ONE LONG
EOR.L D3,(A1)+ ;XOR LEFTMASK INTO DST
SUB #2,D2 ;ADJUST LONGCOUNT FOR DBRA
BLT.S LAST10A ;BR IF NO UNMASKED LONGS
LOOP10A EOR.L D0,(A1)+ ;INVERT A LONG OF DST
DBRA D2,LOOP10A ;LOOP ALL UNMASKED LONGS
LAST10A EOR.L D1,(A1)+ ;XOR RIGHTMASK INTO DST
RTS ;AND RETURN
MERGE10A AND.L D3,D1 ;COMBINE LEFTMASK AND RIGHTMASK
EOR.L D1,(A1)+ ;XOR RIGHTMASK INTO DST
RTS ;AND RETURN
ALIGN Alignment
;--------------------------------------------------------------------
;
; PROCEDURE FastSlabMode, Call when rect clipped and pattern black.
;
; INPUT: D2: MODE, CLOBBERED mode 0=black, 1=xor, 2=white
; OUTPUT: A4: MODECASE
;
; This code has the improvements from QDciPatchROM.a
FastSlabMode
AND #$3,D2 ;GET LO 2 BITS OF MODE
TST.B alphaMode(A6) ;are we drawing in alpha mode? <17>
BEQ.S @1 ;no, use original fast cases <17>
ADDQ #3,D2 ;no, use new fast cases <18>
@1 LEA FASTTAB,A4 ;POINT TO MODE TABLE
SUB.W 0(A4,D2*2),A4 ;GET OFFSET FROM FASTTAB <18>
RTS
FASTTAB DC.W FASTTAB-FAST8 ;BLACK
DC.W FASTTAB-FAST10 ;XOR
DC.W FASTTAB-FAST11 ;WHITE
DC.W FASTTAB-FAST8A ;alpha BLACK (foreground) <17>
DC.W FASTTAB-FAST10A ;alpha XOR <17>
DC.W FASTTAB-FAST11A ;alpha WHITE (background) <17>
COPYHANDLE PROC EXPORT
IMPORT RSetHSize
;----------------------------------------------------------
;
; PROCEDURE COPYHANDLE (SRCH,DSTH: Handle);
;
; Copies SRCH into DSTH, resizing it if necesary.
; OK if srcH is purgeable. <1.7> BAL
;
PARAMSIZE EQU 8
SRCH EQU PARAMSIZE
DSTH EQU SRCH-4
MOVE.L SRCH(SP),D0 ; GET SRC HANDLE
BEQ.S DONE ; =>EXIT IF NO SRC
MOVE.L D0,A0 ; A0 = SRCH
MOVE.L DSTH(SP),D0 ; GET DST HANDLE
BEQ.S DONE ; =>EXIT IF NO DST
MOVE.L D0,A1 ; A1 = DSTH
_HGetState ; get src purge/lock state <1.7> BAL
move.b d0,-(sp) ; save for later restore <1.7> BAL
_HNoPurge ; don't let it purge <1.7> BAL
_GetHandleSize ; D0 = size of SRCH
MOVE.L D0,D1 ; save size in D1
EXG A0,A1 ; get DSTH in A0
JSR RSetHSize ; make it the same size
EXG A0,A1 ; A0 = SRCH, A1 = DSTH
move.b (sp)+,d0 ; get saved state <1.7> BAL
_HSetState ; restore it <1.7> BAL
MOVE.L (A0),A0 ; get SRC pointer
MOVE.L (A1),A1 ; get DST pointer
MOVE.L D1,D0 ; D0 = size
_BlockMoveData ; copy the data
DONE MOVE.L (SP)+,A0 ; get return address
ADDQ #8,SP ; strip parameters
JMP (A0) ; and return
ENDPROC