mac-rom/QuickDraw/QDUtil.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

4733 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-D5/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 JShieldCursor,A1 ;get lo mem vector
JSR (A1) ;and call it
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?
_SHOWCURSOR ;show it
@noShow MOVE.L (SP)+,THEGDEVICE ;RESTORE CURRENT GRAFDEVICE
MOVEM.L (SP)+,D4-D5/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
_BlockMove ; copy the data
DONE MOVE.L (SP)+,A0 ; get return address
ADDQ #8,SP ; strip parameters
JMP (A0) ; and return
ENDPROC