mac-rom/QuickDraw/BitMaps.a

2788 lines
96 KiB
Plaintext

;
; File: BitMaps.a
;
; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM3> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
; so they can conditionalized out of the build.
; <SM2> 6/11/92 stb <sm 6/9/92>stb Add patches and comments from QDciPatchROM.a
; synched-up with QDciPatchROM.a at StdBits, DevLoop, ScrollRect.
; <26> 3/20/91 KON gbm, WRKSHT#SAH-QD-056: Test to see if both src and destination
; are screen devices is backwards.
; <25> 1/25/91 KON DDG: BRC# 81599, Fix problem in SeedFill and CalcMask where area
; is not filled if bottom pixel in 1-pixel-wide line is the seed.
; <24> 1/23/91 KON dba: BRC #79398, Fix code which checks for overlapping gDevices
; in bitsDevLoop.
; <23> 12/13/90 KON If color table is NIL, put color table with special signature
; into picture. [smc]
; <22> 12/3/90 KON Color Table in pictures, take three. If color table is NIL on
; picture creation, put a minimal color table to the picture.
; [smc]
; <21> 11/28/90 gbm Fix problem in bitsdevloop where register a0 was getting
; trashed. [KON with csd]
; <20> 10/30/90 KON If color table is nil, don't save it to the picture! [SMC]
; <19> 9/17/90 BG Removed <17>. 040s are now behaving more reliably.
; <18> 8/2/90 gbm more warnings go away
; <17> 6/25/90 BG Added EclipseNOPs due to flakey 040s.
; <16> 5/31/90 KON Add new call KopyMask, which is CopyMask with a mode and rgn
; parameter.
; <15> 2/28/90 KON Added support for overlapping gDevices. If devices overlap, copy
; only to same device.
; <14> 2/3/90 BAL Fixed typo in previous.
; <13> 2/3/90 BAL Preserve the baseAddresses of screenDevices across the call to
; BitsToPix during the one screen optimization in StdBits.
; <12> 2/2/90 BAL Don't let non-zero pmversions be recorded into pictures
; <11> 2/2/90 BAL Made sure that the baseAddr passed to PutPMData and
; PutDirectPMData is 32-Bit clean. Also reinstantiated the DVB
; optimization for copybitsing from a single screen into a PICT
; since PutPMData and PutDirectPMData now operate in 32-bit
; addressing mode.
; <10> 2/1/90 KON Make register saving conventions the same as in the ROM to save
; space in the ptch.
; <9> 2/1/90 KON Made scrollrect only allocate a new region when it needs to.
; <8> 2/1/90 KON Dither mode should only be cleared for copy into old picture,
; not for copy to screen.
; <7> 1/31/90 KON Clear dither mode when drawing to an old picture by clearing bit 6 of MODE(a6).
; <6> 1/31/90 KON Flatten source pixmap to 1 bit when drawing a picture to
; an old port when a picture is being saved.
; <5> 1/30/90 DDG Fixed ScrollRect to update properly across multiple monitors.
; <4> 1/28/90 BAL Convert DitherCopy mode to copy mode when recording an old pict.
; Also Dither when flattening to 1-bit deep for old picts if the
; original transfer mode requests it.
; <3> 1/18/90 DG Fixed StdBits so that it checks for the source pixmap really
; being a bitmap before it tries to access one of the pixmap
; fields. This is right before it calls PutPMData to transfer the
; scanline to the current picture that is being recorded
; <2> 1/3/90 BAL Removed references to A5 global ScreenBits.baseAddr.
;
;¥1.6 BAL 07/14/1989 For Aurora: Final CQD
; 1.5 BAL 06/30/1989 Fixed bugs in copying from screen(s) into pictures.
;¥1.4 BAL 05/29/1989 Blasting in 32-Bit QuickDraw version 1.0 Final
;
BLANKS ON
STRING ASIS
MACHINE MC68020
;-----------------------------------------------------------
;
;
; **** *** ***** * * * **** ***
; * * * * ** ** * * * * * *
; * * * * * * * * * * * * *
; **** * * * * * * * **** ***
; * * * * * * ***** * *
; * * * * * * * * * * *
; **** *** * * * * * * ***
;
;
;
; QuickDraw Routines to operate on BitMaps.
;
;------------------------------------------------------------------
;
; MODIFICATIONS
;
; 5Jun86 EHB Modified to clear rowBytes flags
; 18Jun86 EHB Call StretchBits instead of RgnBlt
; 5Jul86 EHB Modified CopyBits to work with pixMaps
; 31Jul86 EHB Modified CopyMask to work with depths
; 9Oct86 EHB Added mask parameters to stretchbits calls
; 27Oct86 EHB Modified PackBits for bigger scanlines
; 31OCT86 EHB Rewrote ScrollRect to use CopyBits and EraseRgn
; 3Jan87 CRC pass color param to stretch
; 21Jan87 EHB Minor tweaks to devloop for copybits offscreen
; 23Jan87 CRC clear the pattern bit in case it was accidentally set by the user
; 24Jan87 EHB Bug fix in offscreen copybits when recording picture
; 04Feb87 EHB Didn't preserve enough regs when blitting from screen.
;
;---------------------------- Macintosh II ROMs -----------------------------
;
; 26May87 EHB Rolled in patch to map transfer mode if recording old picture
; 27May87 EHB Rolled in patch to set correct default device in DevLoop
; 27May87 EHB Rolled in patch to force printing through grafProc
; 17Jun88 BAL Added support for direct pixmaps to stdbits picture recording
; 19Sep88 BAL Altered StdBits to get SCREEN FLAG value from _BitsToPix;
; 08Jan89 BAL Vectorized CheckPic
;
;---------------------------- Jackson Pollock 1.0 -----------------------------
;
; 28May89 BAL Tweaked Copybits,CopyMask,DevLoop to not keep derefed port pixmap handles.
; 28May89 BAL StdBits/picture recording randomly mapped new transfer modes to old ones.
; 28May89 BAL Set up oldPic flag in stdBits earlier--not just if from screen!
StdBits PROC EXPORT
IF (&TYPE('PATCHMAC2') = 'UNDEFINED') THEN
EXPORT BitsDevLoop
IMPORT PutPicByte,PutPicWord,PutPicRgn,PutPicData,PutPicOp,SectRect,CopyMask
IMPORT StretchBits,PackBits,BitsToPix,PutPicTable,PutPMData,PortToMap,BitsToMap,SHFTTBL
ELSE
IMPORT PutBigPicData
CheckPic EQU $40820EF2
PutPicWord EQU $4082081E
PutPicRgn EQU $408208B8
PutPicData EQU $408207F0
PutPicOp EQU $4082088A
PutPicLong EQU $40820830
PutPicTable EQU $40820B74
PutPMData EQU $40820E48
SHFTTBL EQU $4081ec92
DevLoop EQU $408245ba
ENDIF
;---------------------------------------------------------------
;
; PROCEDURE StdBits(VAR srcBits: BitMap;
; VAR srcRect: Rect;
; VAR dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle);
;
; as seen in QDciPatchROM.a <sm 6/9/92>stb
; SRC DEVICE RECORDS STORED ON STACK
FLAG EQU 0 ;OFFSET TO FLAG
DEV EQU FLAG+2 ;OFFSET TO DEVICE
RECT EQU DEV+4 ;OFFSET TO RECT
SIZE EQU RECT+8 ;SIZE OF RECORD
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 18
SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
SRCRECT EQU SRCBITS-4 ;LONG, ADDR OF RECT
DSTRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
SRCPIX EQU -(PMREC+CTREC+20) ;PIXMAP + COLOR TABLE
TEMPPIX EQU SRCPIX-PMREC ;PIXMAP
DSTBITS EQU TEMPPIX-4 ;DST BITMAP
GLOBALSRC EQU DSTBITS-8 ;GLOBAL COPY OF SRC RECT
GLOBALDST EQU GLOBALSRC-8 ;GLOBAL COPY OF DST RECT
SRCRECT1 EQU GLOBALDST-8 ;LOCAL COPY OF SRC RECT
DSTRECT1 EQU SRCRECT1-8 ;LOCAL COPY OF DST RECT (MUST FOLLOW SRCRECT1)
RECT1 EQU DSTRECT1-8 ;RESULT OF INTERSECTION
DEFSRC EQU RECT1-SIZE ;DEFAULT SRC RECORD
ENDSRC EQU DEFSRC-4 ;0 FOR TERMINATING SRC LIST
SRCDEV EQU ENDSRC-4 ;CURRENT SRC DEVICE RECORD
ENDDST EQU SRCDEV-4 ;0 FOR TERMINATING DST LIST
DSTDEV EQU ENDDST-4 ;CURRENT DST DEVICE
SRCLIST EQU DSTDEV-4 ;POINTER TO SORTED SRC RECT LIST
DSTLIST EQU SRCLIST-4 ;POINTER TO SORTED DST RECT LIST
SAVEDSP EQU DSTLIST-4 ;SAVED STACK POINTER
LASTSEED EQU SAVEDSP-4 ;LAST COLOR TABLE SEED
SAVEFG EQU LASTSEED-4 ;ORIGINAL FG COLOR
SAVEBK EQU SAVEFG-4 ;ORIGINAL BK COLOR
SAVEHILITE EQU SAVEBK-2 ;SAVED HILITE MODE FLAG
RGNA EQU SAVEHILITE-4 ;FIRST REGION FOR CLIPPING
RGNB EQU RGNA-4 ;SECOND REGION FOR CLIPPING
MASKBITS EQU RGNB-4 ;BITMAP FOR MASK
MASKRECT EQU MASKBITS-4 ;LONG, ADDR OF MASK RECT
isTmpHandle EQU MASKRECT-1 ;BYTE, FLAG SET IF temp memory used <1.5> BAL
OLDPIC EQU isTmpHandle-1 ;BYTE, FLAG SET IF OLD PICTURE <1.5> BAL
VARSIZE EQU OLDPIC ;TOTAL SIZE OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS
_CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE NOTPIC ;BRANCH IF NOT PICSAVE
;
; Set flag in OLDPIC(A6) if recording to old picture. <28May89 BAL>
;
MOVE.L PICSAVE(A3),A0 ;GET PICSAVE HANDLE <26May87 EHB>
MOVE.L (A0),A0 ;POINT TO PICSAVE RECORD <26May87 EHB>
CMP #PICTVERSION,PICVERSION(A0) ;IS IT AN OLD PICTURE? <26May87 EHB>
SEQ OLDPIC(A6) ;yes, set flag <26May87 EHB>
;----------------------------------------------------
;
; CONVERT SRCBITS TO A PIXMAP
; (A5 must contain global ptr)
;
MOVE.L SRCBITS(A6),A1 ;GET POINTER TO SRCBITS
TST ROWBYTES(A1) ;IS IT A BITMAP OR A PIXMAP
SPL D7 ;SET FLAG IF BITMAP
move d7,d6 ;Bits to pix clears pixmap/bitmap bit <30Jan90 KON>
or.b oldPic(a6),d7 ;d7=oldPic|bitMap <28May89 BAL>
LEA SRCPIX(A6),A2 ;COPY INTO SRCPIX
_BitsToPix ;BITMAP -> PIXMAP; RETURNS SCREEN FLAG IN D2 <BAL 19Sep88>
;----------------------------------------------------
;
; GET SHIFT AMOUNT FOR SRC DEPTH INTO D3
;
LEA SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE SRCPIX+PIXELSIZE(A6),D0 ;GET SRC PIXEL SIZE
MOVEQ #0,D3 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D0),D3 ;GET SHIFT AMOUNT
;----------------------------------------------------
;
; IF SRC IS THE SCREEN, THEN USE COPYBITS TO COPY THE SRC TO AN OFFSCREEN BITMAP
; THIS ENSURES THAT SRC IS CONTIGUOUS, ALL ONE DEPTH, ETC.
;
CLR.L RECT1(A6) ;CLEAR HANDLE TO SAVED BITS
TST.B D2 ;IS SRC THE SCREEN? <BAL 19Sep88>
Bne.s doScreen ;Yes, convert it <KON 30Jan90>
tst.b d6 ;is source a bitmap? <KON 30Jan90>
bne notScrn ;YES, don't convert <KON 30Jan90>
tst.b OldPic(a6) ;is dst old port? <KON 30Jan90>
beq notScrn ;No, then don't convert source <KON 30Jan90>
bra doConvert
doScreen
IF 1 THEN ;Can't optimize if screen needs 32-bit addressing
;<dÃb>
;----------------------------------------------------
; If the source is only one screen, copy straight across. (No need for
; temp offscreen pixmap.)
TST.B D7 ;Unless, that is, the dst is an OLD port,
BNE MultiMapSrc ;which'll require flattening.
MOVE.L SRCRECT(A6),A0 ;POINT TO SRC RECTANGLE
LEA SRCRECT1(A6),A1 ;POINT TO PLACE FOR COPY
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
PEA SRCRECT1(A6) ;PUSH COPY OF SRCRECT
NEG.W D1 ;left (D1=topLeft from BitsToPix)
SWAP D1
NEG.W D1 ;top
SWAP D1
MOVE.L D1,-(SP)
_OffsetRect ;SRCRECT1 is the global srcrect. (it used to happen later on)
CLR D4 ;How many devices does src intersect? <pb535a>
MOVE.L DeviceList,A2 ;A0=handle to head of device list
@gdrt
MOVE.L (A2),A2 ;A2->device
TST GDFLAGS(A2) ;IS IT ACTIVE?
BPL.S @nextgd ;=>NO, SKIP TO NEXT
SUBQ #2,SP ;Boolean result
PEA gdRect(A2) ;device global rect
PEA SRCRECT1(A6) ;source bitmap rect in global
PEA DSTRECT1(A6) ;put the intersection here(throwaway).
_SectRect
TST.B (SP)+ ;Any intersection at all?
BEQ.S @nextgd ;=>No, go do the next gd.
ADDQ #1,D4 ;=>Yes, count it. <pb535a>
MOVE.L A2,DSTDEV(A6) ;stash this device ptr here (as SRC)
@nextgd
MOVE.L gdNextGD(A2),D0
MOVE.L D0,A2
BNE.S @gdrt
CMP #1,D4 ;If the srcrect intersects more than <pb535a>
BGT.S MultiMapSrc ;one gdevice, do offscreen map.
MOVE.L DSTDEV(A6),A1 ;A1->the single source gdevice
MOVE.L gdPMap(A1),A1 ;A1=handle to pixmap
MOVE.L (A1),A1 ;A1->pixmap
move.l baseAddr(a1),d4 ;save un-stripped screen base in d4
LEA SRCPIX(A6),A2 ;A2->our local srcpix record
_BitsToPix ;BITMAP -> PIXMAP; RETURNS SCREEN FLAG IN D2
move.l d4,SRCPIX+baseAddr(a6) ;prevent stripping on alternate screens
PEA SRCPIX+bounds(A6) ;Fix bounds for SRCPIX
MOVE.L SRCBITS(A6),A0 ;by offsetting by original source bounds
MOVE.L bounds+topLeft(A0),-(SP)
_OffsetRect
LEA SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE SRCPIX+PIXELSIZE(A6),D0 ;GET SRC PIXEL SIZE (redo for different gdevice)
MOVEQ #0,D3 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D0),D3 ;GET SHIFT AMOUNT (redo for different gdevice)
BRA NOTSCRN ;And pretend source isn't a screen.
MultiMapSrc ;2 or more active gdevices intersected
ENDIF
;----------------------------------------------------
;
; OFFSET SRCRECT TO GLOBAL COORDINATES AND GET SCREEN DEPTH
;
doConvert
MOVE.L SRCRECT(A6),A0 ;POINT TO SRC RECTANGLE
LEA SRCRECT1(A6),A1 ;POINT TO PLACE FOR COPY
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
PEA SRCRECT1(A6) ;PUSH COPY OF SRCRECT
MOVE.L SRCBITS(A6),A0 ;GET SRCBITS
MOVE.L BOUNDS(A0),D0 ;GET BOUNDS.TOPLEFT
NEG D0 ;NEGATE BOUNDS.LEFT
SWAP D0 ;GET BOUNDS.TOP
NEG D0 ;NEGATE BOUNDS.TOP
SWAP D0 ;GET BOUNDS.TOPLEFT
MOVE.L D0,-(SP) ;PUSH BOUNDS.TOPLEFT
_OFFSETRECT ;OFFSET RECT TO GLOBAL COORDINATES
CLR.L -(SP) ;MAKE ROOM FOR HANDLE
PEA SRCRECT1(A6) ;POINT TO GLOBAL RECT
_GETMAXDEVICE ;GET DEEPEST SCREEN DEVICE
MOVE.L (SP)+,D0 ;POP DEVICE HANDLE
BEQ BITSOK ;=>NOT ON SCREEN, DON'T RECORD
;----------------------------------------------------
;
; Set up off screen GDevice for the Copy
; SET TEMP PIXMAP USING INFO FROM DEEPEST SCREEN
;
move.l theGDevice,-(sp) ;save current GDevice <BAL 23Jan89>
move.l d0,theGDevice ;set up offscreen GDevice <BAL 23Jan89>
MOVE.L D0,A0 ;GET HANDLE TO DEEPEST DEVICE
MOVE.L (A0),A0 ;POINT TO DEEPEST DEVICE
MOVE.L GDPMAP(A0),A0 ;GET HANDLE TO ITS PIXMAP
MOVE.L (A0),A0 ;POINT TO PIXMAP
LEA TEMPPIX(A6),A1 ;POINT TO DST
MOVEQ #(PMREC/2)-1,D0 ;GET NUMBER OF WORDS IN RECORD
@0 MOVE (A0)+,(A1)+ ;COPY A WORD
DBRA D0,@0 ;=>REPEAT UNTIL DONE
clr.w TEMPPIX+PMVERSION(A6) ;clear 32bit addressing flag <BAL 15Dec88>
;----------------------------------------------------
;
; SET TEMPPIX.BOUNDS TO SRCRECT
;
MOVE.L SRCRECT(A6),A0 ;POINT AT SRC RECTANGLE
LEA TEMPPIX+BOUNDS(A6),A1 ;POINT AT DST BOUNDS
MOVE.L (A0)+,D1 ;GET TOPLEFT
MOVE.L D1,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,D0 ;GET BOTRIGHT
MOVE.L D0,(A1)+ ;COPY BOTRIGHT
MOVE D0,D5 ;GET A COPY OF RIGHT
SUB D1,D5 ;GET WIDTH IN PIXELS
EXT.L D5 ;MAKE IT LONG
;----------------------------------------------------
;
; FLAG IN D7 is set IF RECORDING A BITMAP or recording to old picture.
; GET DEPTH-SHIFT FOR PIXMAP IN D3 AND ROWBYTES FOR PICTURE IN D5.
; FORCE DEPTH TO 1 IF SRC IS BITMAP OR IF RECORDING OLD PICTURE.
;
MOVEQ #0,D3 ;DEFAULT SHIFT = 0
TST.B D7 ;IS IT A BITMAP? <BAL 28May89>
BNE.S ITSBITS ;=>YES, GO CALCULATE ROWBYTES
LEA SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE TEMPPIX+PIXELSIZE(A6),D2 ;GET BITS PER PIXEL
MOVE.B 0(A0,D2),D3 ;GET SHIFT AMOUNT
ITSBITS LSL.L D3,D5 ;CONVERT PIXELS TO BITS
MOVEQ #15,D2 ;GET 15
ADD.L D2,D5 ;ROUND UP TO NEAREST WORD BOUNDARY
ASR.L #4,D5 ;DIV BY 16
BLE BITSOK ;IGNORE IF NEWROW <= 0
ADD D5,D5 ;DOUBLE FOR NEW ROWBYTES
MOVE D5,TEMPPIX+ROWBYTES(A6) ;COPY ROWBYTES
MOVE D5,D4 ;OLD ROWBYTES := NEW ROWBYTES
TST.B D7 ;IS DST A PIXMAP?
BNE.S NOFLAG ;=>NO, DON'T NEED FLAG
OR #$8000,TEMPPIX+ROWBYTES(A6) ;SET PIXMAP FLAG
NOFLAG
;----------------------------------------------------
;
; ALLOCATE MEMORY FOR TEMP PIXMAP AND COPY TO IT
;
SWAP D1 ;GET LEFTTOP
SWAP D0 ;GET RIGHTBOT
SUB D1,D0 ;GET HEIGHT
MULU D5,D0 ;GET DATA SIZE IN BYTES
move.l d0,d5 ;copy size in d5 <1.5> BAL
clr.b isTmpHandle(a6) ;clear temp memory flag <1.5> BAL
_NEWHANDLE ;ALLOCATE MEMORY FOR BITMAP
beq.s @gotMem ;go use it <1.5> BAL
st isTmpHandle(a6) ;set temp memory flag <1.5> BAL
move.l d5,d0 ;request size <1.5> BAL
_NewTempHandle ;ask for it <1.5> BAL
cmp.l d5,d0 ;did we get it all? <1.5> BAL
bge.s @gotMem ;yes, go use it <1.5> BAL
move.l (sp)+,theGDevice ;restore the current GDevice <1.5> BAL
move.w #-143,qdErr ;return something <1.5> BAL
bra BITSOK ;=>ERROR, JUST TRY TO DRAW <1.5> BAL
@gotMem MOVE.L A0,RECT1(A6) ;SAVE FOR DISPOSE
_HLOCK ;LOCK THE HANDLE
MOVE.L (A0),d0 ;POINT AT THE STORAGE
_rTranslate24To32 ;map address in D0 <02Feb90 BAL>
MOVE.L d0,TEMPPIX+BASEADDR(A6) ;AND SET BASE ADDRESS OF TEMP
MOVE.L PICSAVE(A3),-(SP) ;SAVE PICSAVE ON THE STACK
CLR.L PICSAVE(A3) ;DISABLE PICTURE FOR COPY!
SUBQ #6,SP ;MAKE ROOM FOR RGBCOLOR
MOVE.L SP,-(SP) ;POINT TO VAR RGBCOLOR
_GETFORECOLOR ;SAVE THE RGBFORECOLOR
MOVEQ #BLACKCOLOR,D0 ;GET A LITTLE BLACK
MOVE.L D0,-(SP) ;AND SMACK IT ON THE STACK
_FORECOLOR ;SO OUR COPY'S BACK IN WHACK
PEA SRCPIX(A6) ;PUSH TRIMMED SRC PIXMAP
PEA TEMPPIX(A6) ;PUSH DST PIXMAP
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L (SP),-(SP) ;DSTRECT = SRCRECT
CLR -(SP) ;MODE = SRC COPY
btst.b #6,Mode+1(a6) ;dither? <KON 30Jan90>
beq.s @NoDither ; <KON 30Jan90>
move.w #$40,(sp) ;set dither mode <KON 30Jan90>
@NoDither
CLR.L -(SP) ;NO MASKRGN
_COPYBITS ;COPY THE PIXMAP
MOVE.L SP,-(SP) ;POINT AT FORECOLOR
_RGBFORECOLOR ;RESTORE IT
ADDQ #6,SP ;STRIP FORECOLOR
MOVE.L (SP)+,PICSAVE(A3) ;RESTORE PICTURE STATE
move.l (sp)+,theGDevice ;restore the current GDevice <BAL 23Jan89>
;----------------------------------------------------
;
; COPY TEMPPIX INTO SRCPIX AND USE AS NEW SRC PIXMAP
;
LEA TEMPPIX(A6),A0 ;POINT TO TEMPPIX
LEA SRCPIX(A6),A1 ;POINT TO SRCPIX
MOVEQ #(PMREC/2)-1,D0 ;GET NUMBER OF WORDS IN PIXMAP
@0 MOVE (A0)+,(A1)+ ;COPY A WORD
DBRA D0,@0 ;=>REPEAT UNTIL DONE
NOTSCRN
;----------------------------------------------------
;
; TRIM LOCAL COPY OF PIXMAP
;
LEA SRCPIX(A6),A1 ;POINT TO PIXMAP
MOVE.L BASEADDR(A1),A3 ;GET BASEADDR
MOVE ROWBYTES(A1),D4 ;GET OLD ROWBYTES
AND #nuRBMask,D4 ;CLEAR FLAG BITS
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE TOP(A0),D0 ;GET SRCRECT.TOP
SUB BOUNDS+TOP(A1),D0 ;SKIPTOP:=SRCRECT.TOP-BOUNDS.TOP
BLE.S TOPOK ;CONTINUE IF SKIPTOP NEG
ADD D0,BOUNDS+TOP(A1) ;NEWTOP := SRCRECT TOP
MULU D4,D0 ;CALC VERT OFFSET
ADD.L D0,A3 ;ADJUST BASEADDR
TOPOK MOVE BOTTOM(A0),D0 ;GET SRCRECT.BOTTOM
CMP BOUNDS+BOTTOM(A1),D0 ;IS SRCRECT BOT < BOUNDS BOT ?
BGE.S BOTOK ;NO, CONTINUE
MOVE D0,BOUNDS+BOTTOM(A1) ;YES, TRIM BOUNDS BOTTOM
BOTOK MOVE LEFT(A0),D0 ;GET SRCRECT.LEFT
SUB BOUNDS+LEFT(A1),D0 ;CALC SKIPLEFT
BLE.S LEFTOK ;CONTINUE IF SKIPLEFT NEG
EXT.L D0 ;MAKE IT LONG
LSL.L D3,D0 ;CONVERT PIXELS TO BITS
ASR.L #3,D0 ;DIV BY 8 FOR SKIP BYTES
ADD.L D0,A3 ;OFFSET BASEADDR HORIZ
LSL.L #3,D0 ;BYTES TIMES 8 FOR BITS
ASR.L D3,D0 ;CONVERT BITS TO PIXELS
ADD D0,BOUNDS+LEFT(A1) ;ADD DOTS TO BOUNDS.LEFT
LEFTOK MOVE RIGHT(A0),D0 ;GET SRCRECT.RIGHT
SUB BOUNDS+LEFT(A1),D0 ;CONVERT TO GLOBAL
EXT.L D0 ;MAKE IT LONG
ADDQ.L #7,D0 ;ROUND UP
LSL.L D3,D0 ;CONVERT PIXELS TO BITS
AND #$FFF8,D0 ;TRUNC TO BYTE BOUNDARY
ASR.L D3,D0 ;CONVERT BITS TO PIXELS
ADD BOUNDS+LEFT(A1),D0 ;RETURN TO LOCAL
CMP BOUNDS+RIGHT(A1),D0 ;IS RESULT < BOUNDS.RIGHT ?
BGE.S RIGHTOK ;NO, CONTINUE
MOVE D0,BOUNDS+RIGHT(A1) ;YES, TRIM RIGHT
RIGHTOK
;
; CALC NEW ROWBYTES AFTER TRIMMING
;
MOVE BOUNDS+RIGHT(A1),D5 ;GET TRIMMED RIGHT
SUB BOUNDS+LEFT(A1),D5 ;CALC WIDTH IN PIXELS
EXT.L D5 ;MAKE IT LONG
LSL.L D3,D5 ;CONVERT PIXELS TO BITS
MOVEQ #15,D0 ;GET 15
ADD.L D0,D5 ;ROUND UP TO NEAREST WORD BOUNDARY
ASR.L #4,D5 ;DIV BY 16
BLE BITSOK ;IGNORE IF NEWROW <= 0
ADD D5,D5 ;DOUBLE FOR NEW ROWBYTES
MOVE D5,ROWBYTES(A1) ;COPY ROWBYTES
OR #$8000,ROWBYTES(A1) ;SET PIXMAP FLAG
clr.w SRCPIX+PMVERSION(A6) ;clear 32bit addressing flag <BAL 15Dec88>
;----------------------------------------------------
;
; PUT THE BITMAP TO THE PICTURE
;
MOVEQ #8,D6 ;GET A USEFUL NUMBER
MOVE #opBitsRect,-(SP) ;PUSH OPCODE=BITSRECT
TST.L MASKRGN(A6) ;IS MASKRGN NIL ?
BEQ.S NOTRGN ;YES, CONTINUE
ADD #1,(SP) ;REPLACE OPCODE=BITSRGN (IE. $91)
;FIXED BUG 12/3/83, RP
NOTRGN CMP D6,D5 ;IS NEWROW < 8 ?
Bge.s PACK ;YES, DONT BITPACK
move #1,SRCPIX+PACKTYPE(A6) ;replace with "UnPacked" packType
bra.s NoPack
PACK ADD #8,(SP) ;SET BIT 3 FOR BITPACK
NoPack TST.B D7 ;New Picture?
BNE.S OPOK ;=>NO, can't be direct data
clr.w SrcPix+pmVersion(a6) ;only let version zero be stored in pict.
MOVE.W SRCPIX+pixelType(A6),D2 ;get pixelType in d2 for later %%%
cmp #16,D2 ;is it chunky direct? %%%
bne.s OPOK ;NO, OPCODE IS OK %%%
OR.W #$A,(SP) ;YES, USE $9A AND $9B %%%
bsr PutPicOp ;PUT OPCODE TO THEPIC %%%
MOVE.L #$0FF,-(SP) ;PUT HACK TO PIC %%%
bsr PutPicLong
lea srcPix+packType(a6),a0 ;point at packType
CMP #1,(a0) ;PACKING? <BAL 11Jul88>
beq.s @PackOK ;no, don't need to adjust packType <BAL 11Jul88>
CMP #16,SRCPIX+PIXELSIZE(A6) ;16 bit/pixel? <BAL 15Dec88>
bne.s @pack32 ;no, check 32 bit/pixel packing types <BAL 15Dec88>
move #3,(a0) ;use only supported type
bra.s @PackOK
@pack32 cmp #2,(a0) ;drop pad byte only? <BAL 11Jul88>
beq.s @PackOK ;yes, don't need to adjust packType <BAL 11Jul88>
move #4,(a0) ;replace with only remaining supported packType <BAL 15Dec88>
@PackOK MOVE SRCPIX+BOUNDS+BOTTOM(A6),D1 ; %%%
SUB SRCPIX+BOUNDS+TOP(A6),D1 ;HEIGHT := BOUNDS BOT - TOP %%%
MULU D1,D5 ;SAVE PMDATA SIZE IN D5 %%%
PEA SRCPIX+ROWBYTES(A6) ;PUSH ADDR OF PIXMAP %%%
MOVE #PMREC-4,-(SP) ;PUSH SIZE OF PIXMAP (-BASEADDR)
bsr PutPicData ;PUT PIXMAP TO THEPIC %%%
BRA.S NOTABLE ;SKIP CLUT STUFF %%%
ARITHMODE ;avg addPin addOver subPin trans max subOver min
DC.B srcCopy, srcBic, srcXor, srcOr, srcOr, srcBic, srcXor, srcOr
OPOK bsr PutPicOp ;PUT OPCODE TO THEPIC
MOVEQ #PMREC-4,D0 ;GET SIZE OF PIXMAP (-BASEADDR)
TST.B D7 ;ARE WE RECORDING A BITMAP?
beq.s DOPM ;=>SRC IS BitMap, branch
MOVEQ #BITMAPREC-4,D0 ;GET SIZE OF BITMAP (-BASEADDR)
AND #nuRBMask,SRCPIX+ROWBYTES(A6) ;ELSE BITMAP, CLEAR FLAGS
DOPM PEA SRCPIX+ROWBYTES(A6) ;PUSH ADDR OF BITMAP/PIXMAP
MOVE D0,-(SP) ;PUSH BYTECOUNT
bsr PutPicData ;PUT BITMAP/PIXMAP TO THEPIC
; IF IT'S A PIXMAP, PUT THE COLOR TABLE TO THE PICTURE
TST.B D7 ;IS IT A PIXMAP?
BNE.S NOTABLE ;=>NO, DON'T DO TABLE
MOVE.L SRCPIX+PMTABLE(A6),d0 ;get CTabHandle
beq.s PutMinimalTable ;put minimal table if NIL <20> <KON 30OCT90>
move.l d0, -(SP) ;PUSH CTABHANDLE <20> <KON 30OCT90>
bsr PutPicTable ;ADD TABLE TO THEPIC
bra.s NoTable
;
; The following is a minimal color table. It is put to the picture if a PixMap has
; a NIL color table. <KON 29NOV90>
;
MinimalTable
dc.l 0 ;ctSeed
dc.w 0 ;flags
dc.w 0 ;0-based count of entries -> 1 entry
dc.w cTabSignature,0,0,0 ;ColorSpec for 1 entry with signature
MinTableSize EQU 16
;
; Put the minimal color table to the picture
;
PutMinimalTable
pea MinimalTable ;PUSH DATAPTR <KON 29NOV90>
move #MinTableSize,-(sp) ;GET SIZE IN ENTRIES <KON 29NOV90>
jsr PutPicData ;ADD TO THEPIC <KON 29NOV90>
NOTABLE MOVE.L SRCRECT(A6),-(SP)
MOVE D6,-(SP)
bsr PutPicData ;PUT SRCRECT
MOVE.L DSTRECT(A6),-(SP)
MOVE D6,-(SP)
bsr PutPicData ;PUT DSTRECT
MOVE MODE(A6),D0 ;get desired mode <26May87 EHB>
TST.B OLDPIC(A6) ;is it an old picture? <26May87 EHB>
BEQ.S @ModeOK ;=>no, mode is fine <26May87 EHB>
bclr #6,d0 ;don't record ditherCopy in old Picts
;since the laserWriter driver inverts it.
BTST #5,D0 ;an arithmetic mode? <26May87 EHB>
BEQ.S @ModeOK ;=>no, mode is fine <26May87 EHB>
AND #$07,D0 ;else strip to low 3 bits <26May87 EHB>
MOVE.B ARITHMODE(D0),D0 ;and remap it <26May87 EHB>
@ModeOK MOVE D0,-(SP) ;push mode <26May87 EHB>
bsr PutPicWord ;PUT MODE
TST.L MASKRGN(A6) ;IS MASKRGN NIL ?
BEQ.S NOMASK ;YES, SKIP IT
MOVE.L MASKRGN(A6),-(SP) ;NO, PUSH MASKRGN
bsr PutPicRgn ;PUT MASKRGN TO THEPIC
NOMASK tst.b d7 ;is it a pixmap ? If not, then <17Jan89 DDG>
bne.s @NOTD ;don't check pixmap fields ! <17Jan89 DDG>
cmp #16,SRCPIX+pixelType(A6) ;is it chunky direct? %%%
bne.s @NOTD ;NO, CALL PACKING STUFF %%%
LEA SRCPIX(A6),A0 ;GET PIXMAP POINTER
MOVE.L A0,-(SP) ;PUSH PIXMAP POINTER
MOVE.L A3,-(SP) ;PUSH ADJUSTED BASEADDR
MOVE D4,-(SP) ;PUSH OLD ROWBYTES
bsr PutDirectPMData ;AND PUT DATA TO PICTURE
BRA.S @DONE
@NOTD LEA SRCPIX(A6),A0 ;GET PIXMAP POINTER
MOVE.L A0,-(SP) ;PUSH PIXMAP POINTER
MOVE.L A3,-(SP) ;PUSH ADJUSTED BASEADDR
MOVE D4,-(SP) ;PUSH OLD ROWBYTES
bsr PutPMData ;AND PUT DATA TO PICTURE
@DONE MOVE.L RECT1(A6),D0 ;DID WE ALLOCATE DATA FOR A PIXMAP?
BEQ.S BITSOK ;=>NOPE, DON'T NEED TO DISPOSE
MOVE.L D0,A0 ;ELSE GET HANDLE
tst.b isTmpHandle(a6) ;is it from temp memory? <1.5> BAL
beq.s @notTmp ;no, dispose as usual <1.5> BAL
_DisposeTempBuffer ;yes, dispose as temp memory <1.5> BAL
bra.s BITSOK ; <1.5> BAL
@notTmp _DISPOSHANDLE ;AND DISPOSE OF IT
BITSOK MOVE.L THEPORT(A4),A3 ;RESTORE THEPORT
; CALL HEAVY-DUTY LOOP TO DRAW TO ALL DEVICES
NOTPIC TST PNVIS(A3) ;IS PNVIS >= 0 ?
BLT.S GOHOME ;NO, QUIT
LEA PORTBITS(A3),A0 ;GET DST BITMAP
MOVE.L A0,DSTBITS(A6) ;AND PLACE IN STACK FRAME
MOVE.L VISRGN(A3),RGNA(A6) ;PASS VISRGN
MOVE.L CLIPRGN(A3),RGNB(A6) ;AND CLIPRGN
CLR.L MASKBITS(A6) ;NO MASK BITMAP
CLR.L MASKRECT(A6) ;NO MASK RECTANGLE
_BitsDevLoop ;DRAW TO ALL DEVICES
GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDBITS '
BitsDevLoop
;---------------------------------------------------------------
;
; PROCEDURE DevLoop;
;
; On Entry: A3: GrafPort
; A6: StdBits' stack frame
; DSTBITS(A6): Destination bitmap/pixmap
; RGNA(A6): First region to clip to
; RGNB(A6): Second region to clip to
; MASKBITS(A6): Mask's bitmap
; MASKRECT(A6): Mask's rectangle
;
; D3-D7/A2-A4 have been preserved and can be used.
; from QDciPatchROM.a verbatim <sm 6/9/92>stb
; IF THERE IS ONLY ONE SCREEN DEVICE, THEN DO IT FAST
MOVE.L DEVICELIST,A0 ;GET HEAD OF DEVICE LIST
MOVE.L (A0),A0 ;POINT TO DEVICE
MOVE.L GDNEXTGD(A0),D0 ;CHECK NEXT DEVICE
BNE.S MANYVIDI ;=>GO DO MANY DEVICES
;ciBitsDevTop
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS
MOVE.L MASKBITS(A6),-(SP) ;PUSH MASKBITS
MOVE.L DSTBITS(A6),-(SP) ;PUSH DSTBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L MASKRECT(A6),-(SP) ;PUSH MASKRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
AND #$FFF7,(SP) ;clear the pattern bit in case the user set it
CLR.L -(SP) ;NO PATTERN NEEDED
MOVE.L RGNA(A6),-(SP) ;PUSH FIRST REGION
MOVE.L RGNB(A6),-(SP) ;PUSH SECOND REGION
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK1 ;WAS IT NIL ?
MOVE.L GRAFGLOBALS(A5),A0 ;GET GRAFGLOBALS
MOVE.L WIDEOPEN(A0),(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK1 CLR -(SP) ;pass multicolor flag false
_STRETCHBITS ;CALL STRETCHBITS
RTS
MANYVIDI
; INITIALIZE THE DEFAULT DESTINATION DEVICE LIST
; THE LIST CONSISTS OF ONE DEVICE HANDLE FOLLOWED BY A 0
MOVE.L SP,SAVEDSP(A6) ;SAVE STACK POINTER
LEA DSTDEV(A6),A1 ;POINT TO START OF DEFAULT DST LIST
MOVE.L A1,DSTLIST(A6) ;SAVE POINTER TO DEFAULT DST LIST
MOVE.L THEGDEVICE,A0 ;GET DEFAULT DEVICE <07Jul88 BAL>
MOVE.L A0,(A1)+ ;DSTDEV := DEFAULT SCREEN DEVICE
CLR.L (A1)+ ;CLEAR FLAG AT END OF DST LIST
; INITIALIZE THE DEFAULT SRC DEVICE LIST
; THE LIST CONSISTS OF ONE RECORD POINTER FOLLOWED BY A 0
MOVE.L A1,SRCLIST(A6) ;SAVE POINTER TO DEFAULT SRC RECORD
LEA DEFSRC(A6),A2 ;POINT TO DEFAULT SRC RECORD
MOVE.L A2,(A1)+ ;INSTALL RECORD POINTER INTO LIST
CLR.L (A1)+ ;CLEAR FLAG AT END OF SRC LIST
MOVE.L A0,DEV(A2) ;INITIALIZE DEVICE FIELD OF RECORD
; DETERMINE WHETHER SRC AND DST ARE THE SCREEN AND SET UP DRAWING DIRECTIONS
; MOVE.L MAINDEVICE,A0 ;GET DEFAULT SCREEN DEVICE <10Jul88 BAL>
; MOVE.L (A0),A0 ;POINT TO DEFAULT SCREEN DEVICE
; MOVE.L GDPMAP(A0),A0 ;GET HANDLE TO PIXMAP
; MOVE.L (A0),A0 ;POINT TO PIXMAP
; MOVE.L BASEADDR(A0),D0 ;GET BASE ADDR OF SCREEN IN D0
MOVE.L ScrnBase,D0 ;GET BASE ADDR OF main SCREEN IN D0 <23Dec89 BAL>
MOVE.L DSTBITS(A6),A0 ;GET DESTINATION IN A0
_BITSTOMAP ;GET BIT/PIXMAP IN A0
; MOVE.L A0,DSTBITS(A6) ; <Don't carry derefed port's pixmap across rgbForeColor>
; <28May89 BAL>
MOVE.L A0,A1 ;KEEP DST PIXMAP IN A1
MOVE.L SRCBITS(A6),A0 ;POINT TO SRC BITMAP
_BITSTOMAP ;GET BIT/PIXMAP IN A0
MOVE.L A0,A2 ;SAVE SRC PIXMAP IN A2
CMP.L BASEADDR(A0),D0 ;SRC FROM THE SCREEN?
SEQ D6 ;IF SO, SET SRCSCRN FLAG
CMP.L BASEADDR(A1),D0 ;DST TO THE SCREEN?
SEQ D7 ;IF SO, SET DSTSCRN FLAG
MOVEQ #6,D2 ;ASSUME COPY FROM TOP TO BOTTOM
MOVE.B D6,D5 ;GET SRC FLAG
AND.B D7,D5 ;D5 SET IF SRC AND DST BOTH SCREEN
BEQ.S DIROK ;=>NO, DON'T WORRY ABOUT OVERLAP
; SRC AND DST BOTH ON SCREEN, AND THERE ARE MULTIPLE SCREENS. DETERMINE TRANSFER DIRECTION
MOVEQ #0,D2 ;ELSE ASSUME TRANSFER DOWN AND TO RIGHT
MOVE.L ([SRCRECT,A6]),D0 ;GET TOPLEFT OF SRCRECT
SUB BOUNDS+LEFT(A0),D0 ;CONVERT LEFT TO GLOBAL COORDINATES
MOVE.L ([DSTRECT,A6]),D1 ;GET TOPLEFT OF DSTRECT
SUB BOUNDS+LEFT(A1),D1 ;CONVERT LEFT TO GLOBAL COORDINATES
CMP D1,D0 ;IS SRC <= DST?
BLE.S TORT ;=>IF SO, TRANSFER IS TO RIGHT
ADDQ #2,D2 ;ELSE TRANSFER TO LEFT
TORT SWAP D0 ;GET TOP OF SRCRECT
SWAP D1 ;GET TOP OF DSTRECT
SUB BOUNDS+TOP(A0),D0 ;CONVERT TOP TO GLOBAL COORDINATES
SUB BOUNDS+TOP(A1),D1 ;CONVERT TOP TO GLOBAL COORDINATES
CMP D1,D0 ;IS SRC <= DST?
BLE.S DIROK ;=>IF SO, TRANSFER IS DOWNWARD
ADDQ #4,D2 ;ELSE TRANSFER IS UPWARD
DIROK LEA CMPTBL,A4 ;POINT TO TABLE OF OFFSETS
ADD 0(A4,D2),A4 ;A4 = RECT COMPARE ROUTINE
; COPY SRC RECT AND CONVERT COPY TO GLOBAL COORDINATES
TST.B D6 ;IS SRC THE SCREEN?
BEQ CHKDST ;=>NO, CHECK DEST
MOVE.L SRCRECT(A6),A1 ;POINT TO RECT
LEA GLOBALSRC(A6),A0 ;POINT TO LOCAL COPY
MOVE.L (A1)+,TOPLEFT(A0) ;COPY SRCRECT.TOPLEFT
MOVE.L (A1)+,BOTRIGHT(A0) ;COPY SRCRECT.BOTRIGHT
MOVE.L BOUNDS(A2),D0 ;GET SRCBITS.TOPLEFT
MOVE.L D0,D1 ;LEAVE LEFT IN D0
SWAP D1 ;AND TOP IN D1
SUB D1,(A0)+ ;OFFSET TOP
BVC.S @0 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@0 SUB D0,(A0)+ ;OFFSET LEFT
BVC.S @1 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@1 SUB D1,(A0)+ ;OFFSET BOTTOM
BVC.S @2 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@2 SUB D0,(A0)+ ;OFFSET RIGHT
BVC.S @3 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@3
; FOR EACH SRC DEVICE THAT INTERSECTS WITH THE SRCRECT, BUILD A RECORD ON THE STACK
; EACH RECORD IN LIST CONSISTS OF: [FLAG WORD] [DEVICE HANDLE] [RECTANGLE]
; [FLAG WORD]: O = END OF LIST; 1 = VALID RECORD; -1 = RECORD ALREADY USED IN SORT
MOVE.L DEVICELIST,A2 ;GET HANDLE TO FIRST DEVICE
CLR -(SP) ;[FLAG WORD] := END OF LIST
DONEXT1 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
TST GDFLAGS(A0) ;IS THIS SCREEN ACTIVE?
BPL.S NXTDEV1 ;=>NO, SKIP TO NEXT
CLR.B -(SP) ;MAKE ROOM FOR BOOLEAN RESULT
PEA GLOBALSRC(A6) ;POINT TO SRC RECT
PEA GDRECT(A0) ;POINT AT DEVICE RECT
PEA RECT1(A6) ;GET RESULT IN RECT1
_SECTRECT ;INTERSECT THEM
TST.B (SP)+ ;DID THEY INTERSECT?
BEQ.S NXTDEV1 ;=>NO, KEEP LOOKING
LEA RECT1(A6),A0 ;POINT AT RESULT
MOVE.L 4(A0),-(SP) ;PUSH BOTRIGHT
MOVE.L (A0),-(SP) ;PUSH TOPLEFT
MOVE.L A2,-(SP) ;PUSH CURRENT DEVICE
MOVE #1,-(SP) ;FLAG VALID ENTRY
NXTDEV1 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
MOVE.L GDNEXTGD(A0),D0 ;IS THERE ANOTHER DEVICE IN CHAIN?
MOVE.L D0,A2 ;GET IT INTO A0
BNE.S DONEXT1 ;=>YES, DO NEXT DEVICE
; BUILD SORTED LIST OF POINTERS TO THE DEVICE RECORDS
MOVE.L SP,A2 ;POINT TO FIRST DEVICE
CLR.L -(SP) ;AND FLAG END OF LIST
MOVEQ #0,D1 ;USEFUL CONSTANT
NXTLOOP MOVE.L A2,A0 ;POINT TO START OF LIST
MOVE.L D1,A1 ;INITIALIZE BEST FIT TO NONE
NXTRECT TST FLAG(A0) ;CHECK RECT STATUS?
BMI.S DONEXT ;=>RECT ALREADY USED, SKIP IT
BEQ.S LASTRECT ;=>LAST RECT, DONE WITH THIS LOOP
CMP.L A1,D1 ;SOMETHING TO COMPARE AGAINST?
BEQ.S NORECT ;=>NO, A WINNER BY DEFAULT
JSR (A4) ;COMPARE A0 TO A1
BEQ.S DONEXT ;=>A1 IS BETTER, TRY NEXT
NORECT MOVE.L A0,A1 ;ELSE PUT NEW BEST FIT IN A1
DONEXT ADD #SIZE,A0 ;BUMP TO NEXT RECORD
BRA.S NXTRECT ;=>DO NEXT RECT IN LIST
LASTRECT CMP.L A1,D1 ;DID WE FIND A BEST FIT?
BEQ.S ENDLOOP ;=>NO, ALL DONE
ST FLAG(A1) ;SAY IT'S USED
MOVE.L A1,-(SP) ;AND PUSH RECORD POINTER ONTO STACK
BRA.S NXTLOOP ;=>GO FIND NEXT BEST
ENDLOOP MOVE.L SP,SRCLIST(A6) ;SAVE POINTER TO SRC DEVICE LIST
; COPY DST RECT AND CONVERT COPY TO GLOBAL COORDINATES
CHKDST TST.B D7 ;IS DST THE SCREEN?
BEQ DRAWLOOP ;=>NO, GO TO DRAWING LOOP
MOVE.L DSTRECT(A6),a0 ;POINT TO RECT
LEA GLOBALDST(A6),a1 ;POINT TO LOCAL COPY
MOVE.L (a0)+,TOPLEFT(a1) ;COPY DSTRECT.TOPLEFT
MOVE.L (a0)+,BOTRIGHT(a1) ;COPY DSTRECT.BOTRIGHT
MOVE.L DSTBITS(A6),A0 ;GET DESTINATION IN A0
_BITSTOMAP ;make sure it's not a cportPtr <28May89 BAL>
MOVE.L BOUNDS(a0),D0 ;GET TOPLEFT
MOVE.L D0,D1 ;LEAVE LEFT IN D0
SWAP D1 ;AND TOP IN D1
SUB D1,(a1)+ ;OFFSET TOP
BVC.S @0 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@0 SUB D0,(a1)+ ;OFFSET LEFT
BVC.S @1 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@1 SUB D1,(a1)+ ;OFFSET BOTTOM
BVC.S @2 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@2 SUB D0,(a1)+ ;OFFSET RIGHT
BVC.S @3 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@3
; FOR EACH DST DEVICE THAT INTERSECTS WITH THE DSTRECT, BUILD A RECORD ON THE STACK
; EACH RECORD IN LIST CONSISTS OF: [FLAG WORD] [DEVICE HANDLE] [RECTANGLE]
; [FLAG WORD]: O = END OF LIST; 1 = VALID RECORD; -1 = RECORD ALREADY USED IN SORT
MOVE.L DEVICELIST,A2 ;GET HANDLE TO FIRST DEVICE
CLR -(SP) ;[FLAG WORD] := END OF LIST
DONEXT2 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
TST GDFLAGS(A0) ;IS THIS SCREEN ACTIVE?
BPL.S NXTDEV2 ;=>NO, SKIP TO NEXT
CLR.B -(SP) ;MAKE ROOM FOR BOOLEAN RESULT
PEA GLOBALDST(A6) ;POINT TO DST RECT
PEA GDRECT(A0) ;POINT AT DEVICE RECT
PEA RECT1(A6) ;GET RESULT IN RECT1
_SECTRECT ;INTERSECT THEM
TST.B (SP)+ ;DID THEY INTERSECT?
BEQ.S NXTDEV2 ;=>NO, KEEP LOOKING
LEA RECT1(A6),A0 ;POINT AT RESULT
MOVE.L 4(A0),-(SP) ;PUSH BOTRIGHT
MOVE.L (A0),-(SP) ;PUSH TOPLEFT
MOVE.L A2,-(SP) ;PUSH CURRENT DEVICE
MOVE #1,-(SP) ;FLAG VALID ENTRY
NXTDEV2 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
MOVE.L GDNEXTGD(A0),D0 ;IS THERE ANOTHER DEVICE IN CHAIN?
MOVE.L D0,A2 ;GET IT INTO A0
BNE.S DONEXT2 ;=>YES, DO NEXT DEVICE
; BUILD SORTED LIST OF DEVICES
MOVE.L SP,A2 ;POINT TO FIRST DEVICE
CLR.L -(SP) ;AND FLAG END OF LIST
MOVEQ #0,D1 ;USEFUL CONSTANT
NXTLUP2 MOVE.L A2,A0 ;POINT TO START OF LIST
MOVE.L D1,A1 ;INITIALIZE BEST FIT TO NONE
NXTRCT2 TST FLAG(A0) ;CHECK RECT STATUS?
BMI.S DONXT2 ;=>RECT ALREADY USED, SKIP IT
BEQ.S LSTRCT2 ;=>LAST RECT, DONE WITH THIS LOOP
CMP.L A1,D1 ;SOMETHING TO COMPARE AGAINST?
BEQ.S NORCT2 ;=>NO, A WINNER BY DEFAULT
JSR (A4) ;COMPARE A0 TO A1
BEQ.S DONXT2 ;=>A1 IS BETTER, TRY NEXT
NORCT2 MOVE.L A0,A1 ;ELSE PUT NEW BEST FIT IN A1
DONXT2 ADD #SIZE,A0 ;BUMP TO NEXT RECORD
BRA.S NXTRCT2 ;=>DO NEXT RECT IN LIST
LSTRCT2 CMP.L A1,D1 ;DID WE FIND A BEST FIT?
BEQ.S ENDLUP2 ;=>NO, ALL DONE
ST FLAG(A1) ;SAY IT'S USED
MOVE.L DEV(A1),-(SP) ;AND PUSH DEVICE HANDLE ONTO STACK
BRA.S NXTLUP2 ;=>GO FIND NEXT BEST
ENDLUP2 MOVE.L SP,DSTLIST(A6) ;SAVE POINTER TO DST DEVICE LIST
DRAWLOOP
; IN CASE WE ARE GOING TO SCREEN, SAVE OFF STATE INFO
MOVE.L THEGDEVICE,-(SP) ;SAVE DST DEVICE
MOVE.L SRCDEVICE,-(SP) ;SAVE SRC DEVICE
MOVE.L THEGDEVICE,A0 ;GET HANDLE TO THE GDEVICE
MOVE.L (A0),A0 ;POINT TO THE GDEVICE
MOVE.L GDPMAP(A0),A0 ;GET HANDLE TO ITS PIXMAP
MOVE.L (A0),A0 ;POINT AT PIXMAP
MOVE.L PMTABLE(A0),A0 ;GET COLOR TABLE HANDLE
MOVE.L (A0),A0 ;POINT TO COLOR TABLE
MOVE.L CTSEED(A0),LASTSEED(A6) ;SAVE LAST COLOR TABLE SEED
MOVE.L FGCOLOR(A3),SAVEFG(A6) ;SAVE FG COLOR
MOVE.L BKCOLOR(A3),SAVEBK(A6) ;SAVE BK COLOR
MOVE.B HiliteMode,saveHilite(A6) ;save the hilite state
; MAKE A LOCAL COPY OF THE SRC AND DST RECTS IN SRCRECT1 AND DSTRECT1
; AND SET D7 TO NON-ZERO IF WE ARE STRETCHING
LEA DSTRECT1(A6),A1 ;POINT TO DSTRECT1, SRCRECT1
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE.L (A0)+,D0 ;GET TOPLEFT
MOVE.L D0,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,D7 ;GET BOTRIGHT
MOVE.L D7,(A1)+ ;COPY BOTRIGHT
SUB D0,D7 ;GET DST WIDTH
SWAP D0 ;GET TOP
SWAP D7 ;GET BOTTOM
SUB D0,D7 ;GET DST HEIGHT
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE.L (A0)+,D0 ;GET TOPLEFT
MOVE.L D0,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,D1 ;GET BOTRIGHT
MOVE.L D1,(A1)+ ;COPY BOTRIGHT
SWAP D7 ;GET DST WIDTH
ADD D0,D7 ;SUBTRACT WIDTH OF SRC
SUB D1,D7 ;FROM WIDTH OF DST
SWAP D7 ;GET HEIGHT
SWAP D0 ;GET TOP
SWAP D1 ;GET BOTTOM
ADD D0,D7 ;SUBTRACT HEIGHT OF SRC
SUB D1,D7 ;FROM HEIGHT OF DST
;D7.L <> 0 IF STRETCHING
; FOR EACH DEVICE IN THE SRCLIST, DRAW TO EACH DEVICE IN THE DSTLIST
MOVE.L SRCLIST(A6),A2 ;POINT TO SRCLIST
NXTSRC MOVE.L DSTLIST(A6),A4 ;POINT TO DSTLIST
MOVE.L (A2)+,D0 ;GET NEXT SRC RECORD
MOVE.L D0,A0 ;GET RECORD POINTER
BEQ DONE ;=>NO MORE
MOVE.L DEV(A0),SRCDEVICE ;AND SET SRC DEVICE
NXTDST MOVE.L (A4)+,D1 ;GET NEXT DST DEVICE
BEQ.S NXTSRC ;=>NO MORE
MOVE.L D1,THEGDEVICE ;ELSE SET DST DEVICE
TST.B D6 ;IS SRC THE SCREEN?
BEQ CLIPOK ;=>NO, DON'T CHECK CLIPPING
;
; if source and destination are both screen devices and they overlap, copy only to
; destination devices which are the same gDevice as the source. This will be needed
; for devices which use a mask plane. It assures that items moved around in the mask
; plane are only copied to the mask plane, and items moved around on the screen are
; only copied to the screen. Without this, the mask would goto the screen and vice-versa.
; <KON 2/19/90>
;
tst.b d5 ;are both src and destination the screen? <KON 23JAN91>
beq.s @cont ;=>NO, Don't check for overlap <26>
cmp.l SRCDEVICE,d1 ;are src and destination the same device? <KON 28NOV90>
beq.s @cont ;=>YES, Don't check for overlap
;
; Src and Dst are different screen devices. If the top-left corner of their rectangles
; are the same, assume the devices overlap and don't copy between them.
;
MOVE.L srcDevice,A1 ;handle to source gDevice
move.l (a1),a1 ;pointer to source gDevice
move.l gdRect(a1),d0 ;get rect top.left
move.l theGDevice,a0 ;handle to destination gDevice
move.l (a0),a0 ;pointer to destination gDevice
CMP $24(A0), D0
BGT.S @L5
BLT.S @L2
SWAP D0
CMP gdRect+0(A0), D0
BGT.S @L6
BLT.S @L3
MOVE.L gdRect+4(A1), D0
CMP gdRect+6(A0), D0
BLT.S @L7
BGT.S @L4
BRA.S nxtdst
@L2 SWAP D0
CMP gdRect+0(A0), D0
BGT.S @cont
@L3 MOVE.L gdRect+4(A1), D0
CMP gdRect+6(A0), D0
BLT.S @cont
@L4 SWAP D0
CMP gdRect+4(A0), D0
BLT.S @cont
BRA.S nxtdst
@L5 SWAP D0
CMP gdRect+0(A0), D0
BLT.S @cont
@L6 MOVE.L gdRect+4(A1), D0
CMP gdRect+6(A0), D0
BGT.S @cont
@L7 SWAP D0
CMP gdRect+4(A0), D0
BGT.S @cont
BRA.S nxtdst
@cont
;
; End of <KON 2/19/90>
;
; CLIP SRCRECT TO SRC DEVICE BOUNDARIES
MOVE.L -4(A2),A0 ;POINT TO SOURCE RECORD
ADDQ #RECT,A0 ;POINT TO CLIPPED RECT
MOVE.L (A0)+,D0 ;GET GLOBAL CLIPPED.TOPLEFT
MOVE.L (A0)+,D1 ;GET GLOBAL CLIPPED.BOTRIGHT
CMP.L GLOBALSRC+TOPLEFT(A6),D0 ;WAS TOPLEFT TRIMMED?
BNE.S DOTRIM ;=>YES, TRIM SRC, DST RECTS
CMP.L GLOBALSRC+BOTRIGHT(A6),D1 ;WAS BOTRIGHT TRIMMED?
BEQ.S CLIPOK ;=>NO, DON'T TRIM SRC, DST RECTS
DOTRIM MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
LEA DSTRECT1(A6),A1 ;POINT TO DSTRECT1, SRCRECT1
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
SUB GLOBALSRC+LEFT(A6),D0 ;IS LEFT CLIPPED ON DEVICE?
BLE.S @1 ;=>LEFT OK
ADD D0,SRCRECT1+LEFT(A6) ;ELSE TRIM SRC
ADD D0,DSTRECT1+LEFT(A6) ;AND DST
@1 SWAP D0 ;GET TOP
SUB GLOBALSRC+TOP(A6),D0 ;IS TOP CLIPPED ON DEVICE?
BLE.S @2 ;=>TOP OK
ADD D0,SRCRECT1+TOP(A6) ;ELSE TRIM SRC
ADD D0,DSTRECT1+TOP(A6) ;AND DST
@2 SUB GLOBALSRC+RIGHT(A6),D1 ;IS RIGHT CLIPPED ON DEVICE?
BPL.S @3 ;=>RIGHT OK
ADD D1,SRCRECT1+RIGHT(A6) ;ELSE TRIM SRC
ADD D1,DSTRECT1+RIGHT(A6) ;AND DST
@3 SWAP D1 ;GET BOTTOM
SUB GLOBALSRC+BOTTOM(A6),D1 ;IS BOTTOM CLIPPED ON DEVICE?
BPL.S @4 ;=>BOTTOM OK
ADD D1,SRCRECT1+BOTTOM(A6) ;ELSE TRIM SRC
ADD D1,DSTRECT1+BOTTOM(A6) ;AND DST
@4 TST.L D7 ;ARE WE SCALING?
BEQ.S CLIPOK ;=>YES, DON'T NEED TO MAP DST
LEA SRCRECT1(A6),A0 ;ELSE GET TRIMMED SRC
LEA DSTRECT1(A6),A1 ;AND SAVE AS UNMAPPED TRIMMED DST
MOVE.L (A0)+,(A1)+ ;COPY SRCRECT1 TO DSTRECT1
MOVE.L (A0)+,(A1)+
PEA DSTRECT1(A6) ;PUSH RECT TO BE MAPPED
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRC RECTANGLE
MOVE.L DSTRECT(A6),-(SP) ;PUSH DST RECTANGLE
_MAPRECT ;MAP RECTANGLE TO DST COORDINATES
CLIPOK MOVE.B saveHilite(A6),HiliteMode ;RESTORE HILITE FLAGS
TST PORTBITS+ROWBYTES(A3) ;IS IT AN OLD GRAFPORT?
BPL DOIT ;=>YES, COLORS ARE OK
MOVE.L THEGDEVICE,A0 ;GET THE DST DEVICE
MOVE.L (A0),A0 ;POINT AT IT
MOVE.L GDPMAP(A0),A0 ;GET PIXMAP
MOVE.L (A0),A0 ;POINT AT IT
MOVE.L PMTABLE(A0),A0 ;GET COLOR TABLE
MOVE.L (A0),A0 ;POINT AT IT
MOVE.L CTSEED(A0),D0 ;GET SEED
CMP.L LASTSEED(A6),D0 ;SAME AS CURRENT SEED?
BEQ.S DOIT ;=>YES, COLORS ARE OK
MOVE.L D0,LASTSEED(A6) ;SAVE LAST COLOR TABLE SEED
SUBQ #6,SP ;MAKE ROOM FOR A COLOR RECORD
CLR.L -(SP) ;CLEAR INDEX, FLAGS WORDS
; This is a patch rolled in <6Jun87 EHB>
; The idea here is that to keep the index field in the grafPort valid, we must
; check to see whether we should use palette manager or not.
MOVE.L GrafVars(A3),D0 ;get the grafVars handle
BEQ.S @NoPlt ;=>none there
MOVE.L D0,A0 ;get grafVars handle
MOVE.L (A0),A0 ;point at grafVars
TST.L PmFgColor(A0) ;is there a palette?
BEQ.S @NoPlt ;=>no, continue
MOVE PmFlags(A0),D2 ;else get flags
MOVE PmBkIndex(A0),2(SP) ;save bk index
BTST #PmBkBit,D2 ;bk set by palette mgr?
SNE (SP) ;if so set flag
BTST #PmFgBit,D2 ;fg set by palette mgr?
BEQ.S @NoPlt ;=>no, continue
MOVE PmFgIndex(A0),-(SP) ;else push last index
_PmForeColor ;and set that color
BRA.S @NoPlt1 ;=>no, do old way
@NoPlt PEA 4(SP) ;POINT AT RECORD FOR RGBFC
MOVE.L (SP),-(SP) ;AND AGAIN FOR GETFC
_GETFORECOLOR ;GET THE FOREGROUND COLOR
_RGBFORECOLOR ;SET THE FOREGROUND COLOR
@NoPlt1 TST.B (SP) ;bk set by palette mgr?
BEQ.S @NoPlt2 ;=>no, do old way
MOVE 2(SP),-(SP) ;else push bk index
_PmBackColor ;and set that color
BRA.S @BkDone ;=>done setting colors
@NoPlt2 PEA 4(SP) ;POINT AT RECORD
MOVE.L (SP),-(SP) ;AND AGAIN FOR GETFC
_GETBACKCOLOR ;GET THE BACKGROUND COLOR
_RGBBACKCOLOR ;SET THE BACKGROUND COLOR
@BkDone ADD #10,SP ;STRIP THE RECORD
DOIT MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS
MOVE.L MASKBITS(A6),-(SP) ;PUSH MASKBITS
MOVE.L DSTBITS(A6),-(SP) ;PUSH DSTBITS
PEA SRCRECT1(A6) ;PUSH SRCRECT
MOVE.L MASKRECT(A6),-(SP) ;PUSH MASKRECT
PEA DSTRECT1(A6) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
AND #$FFF7,(SP) ;clear the pattern bit in case the user set it
CLR.L -(SP) ;NO PATTERN NEEDED
MOVE.L RGNA(A6),-(SP) ;PUSH FIRST REGION
MOVE.L RGNB(A6),-(SP) ;PUSH SECOND REGION
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK ;WAS IT NIL ?
MOVE.L GRAFGLOBALS(A5),A0 ;GET GRAFGLOBALS
MOVE.L WIDEOPEN(A0),(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK CLR -(SP) ;pass multicolor flag false
_STRETCHBITS ;CALL STRETCHBITS
BRA.S NXTDST ;=>TRY NEXT DESTINATION
DONE MOVE.L (SP)+,SRCDEVICE ;RESTORE SRC DEVICE
MOVE.L (SP)+,THEGDEVICE ;RESTORE DST DEVICE
MOVE.L SAVEFG(A6),FGCOLOR(A3) ;RESTORE FG COLOR
MOVE.L SAVEBK(A6),BKCOLOR(A3) ;RESTORE BK COLOR
BSET #HILITEBIT,HILITEMODE ;TURN OFF HILITING
MOVE.L SAVEDSP(A6),SP ;RESTORE THE STACK POINTER
RTS
;---------------------------------------------------------------
;
; ROUTINES TO COMPARE THE RECT IN A0 TO THE RECT IN A1.
; RETURN TRUE IF SPECIFIED RELATIONSHIP TRUE.
CMPTBL DC.W UPLEFT-CMPTBL
DC.W UPRIGHT-CMPTBL
DC.W DNLEFT-CMPTBL
DC.W DNRIGHT-CMPTBL
; IS THE RECT IN A0 TO THE UPPER LEFT OF THE RECT IN A1?
UPLEFT MOVE RECT+BOTTOM(A0),D0 ;GET BOTTOM OF NEW RECT
CMP RECT+TOP(A1),D0 ;IS IT ABOVE OLD RECT?
BLE.S XTRUE ;=>YES, RETURN TRUE
MOVE RECT+RIGHT(A0),D0 ;GET RIGHT OF NEW RECT
CMP RECT+LEFT(A1),D0 ;IS IT TO LEFT OF NEW RECT
BLE.S XTRUE ;=>YES, RETURN TRUE
XFALSE MOVEQ #0,D0 ;SET FLAG FALSE
RTS ;AND RETURN
XTRUE MOVEQ #1,D0 ;SET FLAG TRUE
RTS ;AND RETURN
; IS THE RECT IN A0 TO THE LOWER LEFT OF THE RECT IN A1?
DNLEFT MOVE RECT+TOP(A0),D0 ;GET TOP OF NEW RECT
CMP RECT+BOTTOM(A1),D0 ;IS IT BELOW OLD RECT?
BGE.S XTRUE ;=>YES, RETURN TRUE
MOVE RECT+RIGHT(A0),D0 ;GET RIGHT OF NEW RECT
CMP RECT+LEFT(A1),D0 ;IS IT TO LEFT OF NEW RECT
BLE.S XTRUE ;=>YES, RETURN TRUE
BRA.S XFALSE ;=>ELSE RETURN FALSE
; IS THE RECT IN A0 TO THE UPPER RIGHT OF THE RECT IN A1?
UPRIGHT MOVE RECT+BOTTOM(A0),D0 ;GET BOTTOM OF NEW RECT
CMP RECT+TOP(A1),D0 ;IS IT ABOVE OLD RECT?
BLE.S XTRUE ;=>YES, RETURN TRUE
MOVE RECT+LEFT(A0),D0 ;GET LEFT OF NEW RECT
CMP RECT+RIGHT(A1),D0 ;IS IT TO RIGHT OF NEW RECT
BGE.S XTRUE ;=>YES, RETURN TRUE
BRA.S XFALSE ;=>ELSE RETURN FALSE
; IS THE RECT IN A0 TO THE LOWER RIGHT OF THE RECT IN A1?
DNRIGHT MOVE RECT+TOP(A0),D0 ;GET TOP OF NEW RECT
CMP RECT+BOTTOM(A1),D0 ;IS IT BELOW OLD RECT?
BGE.S XTRUE ;=>YES, RETURN TRUE
MOVE RECT+LEFT(A0),D0 ;GET LEFT OF NEW RECT
CMP RECT+RIGHT(A1),D0 ;IS IT TO RIGHT OF NEW RECT
BGE.S XTRUE ;=>YES, RETURN TRUE
BRA.S XFALSE ;=>ELSE RETURN FALSE
CopyBits PROC EXPORT
IMPORT ShieldCursor,ShowCursor,StretchBits,BitsToMap,PortToMap,GODEVLOOP
;---------------------------------------------------------------
;
; PROCEDURE CopyBits(srcBits,dstBits: BitMap;
; srcRect,dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle *);
;
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE EQU 22 ;TOTAL BYTES OF PARAMS
SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
DSTBITS EQU SRCBITS-4 ;LONG, ADDR OF BITMAP
SRCRECT EQU DSTBITS-4 ;LONG, ADDR OF RECT
DSTRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
SRCRECT1 EQU -8 ;LOCAL SRC RECT
DSTRECT1 EQU SRCRECT1-8 ;LOCAL DST RECT (MUST FOLLOW SRCRECT1)
VARSIZE EQU DSTRECT1 ;SIZE OF LOCAL VARS
LINK A6,#VARSIZE ;NO LOCAL VARS
MOVEM.L d2/D6-D7/A2-A4,-(SP) ;SAVE REGS (save d2 for MS Works) <01Apr89 BAL>
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
MOVE.L SRCBITS(A6),A0 ;POINT TO SRCBITS
_BITSTOMAP ;GET POINTER TO BIT/PIXMAP IN A0
MOVE.L A0,A2 ;AND SAVE IN A2
; MOVE.L SCREENBITS+BASEADDR(A4),D6 ;GET BASE ADDRESS OF SCREEN
MOVE.L ScrnBase,D6 ;GET BASE ADDRESS OF main SCREEN
MOVE.L BASEADDR(A2),D7 ;GET SRCBITS.BASEADDR
CMP.L D6,D7 ;IS SRC FROM THE SCREEN ?
BNE.S SRCOK ;NO, CONTINUE
MOVE.L SRCRECT(A6),-(SP) ;YES, PUSH SRCRECT
MOVE.L BOUNDS+TOPLEFT(A2),-(SP) ;PUSH OFFSET POINT
_SHIELDCURSOR ;HIDE THE CURSOR IF IN SRCRECT
;-----------------------------------------------------
;
; TEST IF DST IS TO THEPORT, (IF SO WE CLIP)
;
SRCOK MOVE.L DSTBITS(A6),A0 ;POINT TO DSTBITS
_BITSTOMAP ;GET POINTER TO BIT/PIXMAP IN A0
MOVE.L A0,A1 ;SAVE IN A1
MOVE.L A3,D0 ;IS THEPORT NIL ?
BEQ.S NOTPORT ;YES, NOT TO THEPORT
BTST #0,D0 ;IS THEPORT ODD ?
BNE.S NOTPORT ;YES, NOT TO THEPORT
MOVE.L A3,A0 ;GET THEPORT
_PORTTOMAP ;CONVERT PORT TO BIT/PIXMAP
MOVE.L BASEADDR(A1),D1 ;GET DST.BASEADDR
CMP.L BASEADDR(A0),D1 ;IS PORTBITS.BASEADDR SAME ?
BEQ.S BASEOK ;YES, BASE IS SAME <26May87 EHB>
; IF BASEADDR = ROMBASE THEN GO THROUGH GRAFPROC TO MAKE PRINTING WORK
CMP.L D6,D1 ;DST.BASEADDR SAME AS SCREEN? <26May87 EHB>
BNE.S NOTPORT ;NO, NOT TO THE PORT <26May87 EHB>
move.l RomBase,d0 ;pick up rombase <10Apr89 BAL/JNP>
CMP.L BASEADDR(A0),d0 ;IS PORTBITS.BASEADDR ROM? <26May87 EHB>
BNE.S NOTPORT ;=>NO, NOT PORT <26May87 EHB>
BRA TOPORT ;=>ELSE GO THROUGH GRAFPROC <26May87 EHB>
BASEOK MOVE.L BOUNDS(A0),D0 ;GET PORT BOUNDS TOPLEFT
CMP.L BOUNDS(A1),D0 ;IS BOUNDS TOPLEFT SAME ?
BEQ TOPORT ;YES, ITS PROBABLY TO THEPORT
;
; DST IS DEFINITELY NOT TO THEPORT, SO WE CAN'T USE THE CAPTURE PROC.
; StretchBits(srcBits,maskBits,dstBits,srcRect,maskRect,dstRect,mode,pattern,wideOpen,wideOpen,maskRgn);
;
NOTPORT
; if src or dst is the screen, then call devloop
CMP.L D6,D7 ;is dst the screen?
BEQ UseDevLoop ;=>yes, use device loop
; The dst is not the screen so make sure the fgcolor and bkcolor are in
; sync with the dst gdevice in order to make offscreen pixmap copying independent
; of the depth of thePort's pixmap. <BAL 07Jul88>
movem.l d1/a1,-(sp) ;save
SUBQ #6,SP ;MAKE ROOM FOR A COLOR RECORD <BAL 07Jul88>
CLR.L -(SP) ;CLEAR INDEX, FLAGS WORDS <BAL 07Jul88>
PEA 4(SP) ;POINT AT RECORD FOR RGBFC <BAL 07Jul88>
MOVE.L (SP),-(SP) ;AND AGAIN FOR GETFC <BAL 07Jul88>
_GETFORECOLOR ;GET THE FOREGROUND COLOR <BAL 07Jul88>
_RGBFORECOLOR ;SET THE FOREGROUND COLOR <BAL 07Jul88>
PEA 4(SP) ;POINT AT RECORD <BAL 07Jul88>
MOVE.L (SP),-(SP) ;AND AGAIN FOR GETFC <BAL 07Jul88>
_GETBACKCOLOR ;GET THE BACKGROUND COLOR <BAL 07Jul88>
_RGBBACKCOLOR ;SET THE BACKGROUND COLOR <BAL 07Jul88>
ADD #10,SP ;STRIP THE RECORD <BAL 07Jul88>
movem.l (sp)+,d1/a1 ;restore
CMP.L D6,D1 ;is src the screen?
BEQ.S UseDevLoop ;=>yes, use device loop
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS (not derefed) <BAL 28May89>
CLR.L -(SP) ;NO MASK
MOVE.L DSTBITS(A6),-(SP) ;PUSH DSTBITS (not derefed) <BAL 28May89>
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
CLR.L -(SP) ;NO MASKRECT)
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
AND #$FFF7,(SP) ;clear the pattern bit in case the user set it
CLR.L -(SP) ;NO PATTERN
MOVE.L WIDEOPEN(A4),-(SP) ;PUSH WIDEOPEN
MOVE.L (SP),-(SP) ;PUSH WIDEOPEN
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK ;WAS IT NIL ?
MOVE.L WIDEOPEN(A4),(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK CLR -(SP) ;pass multicolor flag false
_STRETCHBITS ;CALL STRETCHBITS
BRA CLEANUP ;AND CONTINUE
UseDevLoop
; CALL GODEVLOOP WITH SAME PARAMETERS AS STDBITS SO IT CAN USE DEVLOOP
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS (not derefed) <BAL 28May89>
MOVE.L DSTBITS(A6),A1 ;Pass DSTBITS (not derefed) <BAL 28May89>
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN (NIL OK)
JSR GODEVLOOP ;GO CALL DEVICE LOOP
BRA CLEANUP ;AND CONTINUE
;
; DST IS PROBABLY TO THEPORT, SO WE USE THE CAPTURE PROC.
;
; If we are drawing to an old grafport and the grafProc has been replaced,
; convert to bitMap first
;____________________________________________________________________________________
TOPORT MOVE rowBytes(A2),D1 ;is src an old bitMap?
BPL @ProcOK ;=>yes, it's safe
TST portBits+rowBytes(A3) ;is port old or new
BMI @ProcOK ;=>new is safe too
MOVE.L grafProcs(A3),D0 ;have the grafProcs been replaced?
BEQ @ProcOK ;=>no, use port
MOVE.L JStdBits,A1 ;get piece of trap table
EXG A1,D0 ;get grafProc pointer
CMP.L bitsProc(A1),D0 ;has it been replaced?
BEQ @ProcOK ;=>no, use port
; we have to do the conversion
@1 MOVE.L A0,-(SP) ;save dstBits
SUB #18,SP ;make room for bitMap, handle
MOVEQ #0,D0 ;clear high word
MOVE D1,D0 ;get rowbytes
LSL #3,D0 ;convert rowBytes to bits
MOVE pixelSize(A2),D1 ;get pixel size of source
DIVU D1,D0 ;get new rowBits
MOVEQ #15,D2 ;get 15
ADD.L D2,D0 ;round rowBits to nearest word
ASR.L #4,D0 ;divide by 16
BLE @Abort ;abort if newRow <= 0
ADD D0,D0 ;double for new rowBytes
MOVE D0,ROWBYTES(SP) ;set new rowBytes
; ALLOCATE MEMORY FOR TEMP BITMAP AND COPY TO IT
MOVE.L bounds+topLeft(A2),D1 ;get topLeft
MOVE.L bounds+botRight(A2),D2 ;get botRight
MOVE.L D1,bounds+topLeft(SP) ;set new topLeft
MOVE.L D2,bounds+botRight(SP) ;set new botRight
SWAP D1 ;get top
SWAP D2 ;get bottom
SUB D1,D2 ;get width
MULU D2,D0 ;get date size in bytes
_NEWHANDLE ;ALLOCATE MEMORY FOR BITMAP
BNE.S @Abort ;=>error, don't draw at all
MOVE.L A0,14(SP) ;SAVE FOR DISPOSE
_HLOCK ;LOCK THE HANDLE
MOVE.L (A0),A0 ;POINT AT THE STORAGE
MOVE.L A0,BASEADDR(SP) ;AND SET BASE ADDRESS OF SRCBITS
MOVE.L PICSAVE(A3),-(SP) ;SAVE PICSAVE ON THE STACK
CLR.L PICSAVE(A3) ;DISABLE PICTURE FOR COPY!
SUBQ #6,SP ;MAKE ROOM FOR RGBCOLOR
MOVE.L SP,-(SP) ;POINT TO VAR RGBCOLOR
_GETFORECOLOR ;SAVE THE RGBFORECOLOR
MOVEQ #BLACKCOLOR,D0 ;GET A LITTLE BLACK
MOVE.L D0,-(SP) ;AND SMACK IT ON THE STACK
_FORECOLOR ;SO OUR COPY'S BACK IN WHACK
MOVE.L SRCBITS(A6),-(SP) ;push source = caller's source
PEA 14(SP) ;push dst = our bitMap
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L (SP),-(SP) ;DSTRECT = SRCRECT
CLR -(SP) ;MODE = SRC COPY
btst #6,mode+1(a6) ;is the ditherCopy bit set
beq.s @noDither
move.w #$40,(sp) ;yes, use ditherCopy instead
@noDither CLR.L -(SP) ;NO MASKRGN
_COPYBITS ;COPY THE PIXMAP
MOVE.L SP,-(SP) ;POINT AT FORECOLOR
_RGBFORECOLOR ;RESTORE IT
ADDQ #6,SP ;STRIP FORECOLOR
MOVE.L (SP)+,PICSAVE(A3) ;RESTORE PICTURE STATE
MOVE.L SP,-(SP) ;PUSH SRCBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN (NIL OK)
MOVE.L GRAFPROCS(A3),D0 ;IS GRAFPROCS NIL ?
MOVE.L D0,A0
MOVE.L BITSPROC(A0),A0 ;NO, GET PROC PTR
JSR (A0) ;CALL IT
MOVE.L 14(SP),A0 ;get handle
_DisposHandle ;and dispose it
@Abort ADD #18,SP ;strip off bitMap, handle
MOVE.L (SP)+,A0 ;restore dstBits pointer
bra.s CLEANUP ;and return <PB302>
;
; CallBits(srcBits,srcRect,dstRect,mode,maskRgn)
;
@ProcOK
MOVE.L A2,-(SP) ;PUSH SRCBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN (NIL OK)
MOVE.L GRAFPROCS(A3),D0 ;IS GRAFPROCS NIL ?
MOVE.L JStdBits,A0 ;get piece of trap table
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L BITSPROC(A0),A0 ;NO, GET PROC PTR
USESTD JSR (A0) ;CALL IT
CLEANUP CMP.L D6,D7 ;WAS SRC FROM THE SCREEN ?
BNE.S DONE ;NO, CONTINUE
_SHOWCURSOR ;YES, REPLACE CURSOR
DONE MOVEM.L (SP)+,d2/D6-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'COPYBITS'
GoDevLoop PROC EXPORT
;---------------------------------------------------------------
;
; PROCEDURE GoDevLoop( VAR srcBits: BitMap;
; VAR srcRect: Rect;
; VAR dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle);
;
; This is a mock version of StdBits used for calling DevLoop
; for transfers from multiple screen devices.
; A4 = QUICKDRAW GLOBALS
; A3 = THEPORT
; A1 = DSTBITS
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 18
SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
SRCRECT EQU SRCBITS-4 ;LONG, ADDR OF RECT
DSTRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
; SRC DEVICE RECORDS STORED ON STACK
FLAG EQU 0 ;OFFSET TO FLAG
DEV EQU FLAG+2 ;OFFSET TO DEVICE
RECT EQU DEV+4 ;OFFSET TO RECT
SIZE EQU RECT+8 ;SIZE OF RECORD
SRCPIX EQU -(PMREC+CTREC+20) ;PIXMAP + COLOR TABLE
TEMPPIX EQU SRCPIX-PMREC ;PIXMAP
DSTBITS EQU TEMPPIX-4 ;DST BITMAP
GLOBALSRC EQU DSTBITS-8 ;GLOBAL COPY OF SRC RECT
GLOBALDST EQU GLOBALSRC-8 ;GLOBAL COPY OF DST RECT
SRCRECT1 EQU GLOBALDST-8 ;LOCAL COPY OF SRC RECT
DSTRECT1 EQU SRCRECT1-8 ;LOCAL COPY OF DST RECT (MUST FOLLOW SRCRECT1)
RECT1 EQU DSTRECT1-8 ;RESULT OF INTERSECTION
DEFSRC EQU RECT1-SIZE ;DEFAULT SRC RECORD
ENDSRC EQU DEFSRC-4 ;0 FOR TERMINATING SRC LIST
SRCDEV EQU ENDSRC-4 ;CURRENT SRC DEVICE RECORD
ENDDST EQU SRCDEV-4 ;0 FOR TERMINATING DST LIST
DSTDEV EQU ENDDST-4 ;CURRENT DST DEVICE
SRCLIST EQU DSTDEV-4 ;POINTER TO SORTED SRC RECT LIST
DSTLIST EQU SRCLIST-4 ;POINTER TO SORTED DST RECT LIST
SAVEDSP EQU DSTLIST-4 ;SAVED STACK POINTER
LASTSEED EQU SAVEDSP-4 ;LAST COLOR TABLE SEED
SAVEFG EQU LASTSEED-4 ;ORIGINAL FG COLOR
SAVEBK EQU SAVEFG-4 ;ORIGINAL BK COLOR
SAVEHILITE EQU SAVEBK-2 ;SAVED HILITE MODE FLAG
RGNA EQU SAVEHILITE-4 ;FIRST REGION FOR CLIPPING
RGNB EQU RGNA-4 ;SECOND REGION FOR CLIPPING
MASKBITS EQU RGNB-4 ;BITMAP FOR MASK
MASKRECT EQU MASKBITS-4 ;LONG, ADDR OF MASK RECT
VARSIZE EQU MASKRECT ;TOTAL SIZE OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STDBITS STACK FRAME
MOVEM.L D3-D7,-(SP) ;SAVE REGISTERS
MOVE.L A1,DSTBITS(A6) ;SET UP DSTBITS
MOVE.L WIDEOPEN(A4),RGNA(A6) ;SET FIRST REGION TO WIDEOPEN
MOVE.L WIDEOPEN(A4),RGNB(A6) ;SET SECOND REGION TO WIDEOPEN
CLR.L MASKBITS(A6) ;NO MASK BITMAP
CLR.L MASKRECT(A6) ;NO MASK RECTANGLE
_BitsDevLoop ;DRAW TO ALL DEVICES
MOVEM.L (SP)+,D3-D7 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'GODEVLOO'
CopyCIcon PROC EXPORT
EXPORT CopyMask
IMPORT PORTTOMAP,BITSTOMAP,CMDevLoop
;--------------------------------------------------------------
;
; PROCEDURE CopyCIcon(srcBits,maskBits,dstBits: BitMap;
; srcRect,maskRect,dstRect: Rect);
;
; Same as CopyMask but accepts another clipping region in A0
;
bra.s share
;--------------------------------------------------------------
;
; PROCEDURE CopyMask(srcBits,maskBits,dstBits: BitMap;
; srcRect,maskRect,dstRect: Rect);
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE EQU 24 ;total bytes of params
SRCBITS EQU PARAMSIZE+8-4 ;long, addr of BitMap
MASKBITS EQU SRCBITS-4 ;long, addr of BitMap
DSTBITS EQU MASKBITS-4 ;long, addr of BitMap
SRCRECT EQU DSTBITS-4 ;long, addr of Rect
MASKRECT EQU SRCRECT-4 ;long, addr of Rect
DSTRECT EQU MASKRECT-4 ;long, addr of Rect
VARSIZE EQU 0
CopyMask
sub.l a0,a0 ;remember no maskrgn
share LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE WORK REGISTERS FOR DEVLOOP
; SET UP REGISTERS FOR CALLING CMDEVLOOP
MOVE.L DSTBITS(A6),A1 ;GET DST BIT/PIXMAP
MOVE.L MASKBITS(A6),D0 ;GET MASK BIT/PIXMAP
MOVE.L MASKRECT(A6),D1 ;GET MASK RECTANGLE
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;GET THE PORT IN A3 FOR DEVLOOP
MOVE.L WIDEOPEN(A4),D2 ;ASSUME NO CLIPPING FOR FIRST RGN
MOVE.L D2,D3 ;ASSUME NO CLIPPING FOR SECOND RGN
; PUSH PARAMETERS FOR CALLING CMDEVLOOP (SAME AS STDBITS)
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRC BIT/PIXMAP
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRC RECTANGLE
MOVE.L DSTRECT(A6),-(SP) ;PUSH DST RECTANGLE
CLR -(SP) ;SRC COPY MODE
MOVE.L D2,-(SP) ;MASKRGN = WIDEOPEN
tst.l a0 ;a real maskRgn?
beq.s srcOK ;no, skip it
move.l a0,(sp) ;yes, overwrite wideOpen
;-----------------------------------------------------
;
; TEST IF DST IS TO THEPORT, (IF SO WE CLIP)
;
SRCOK MOVE.L DSTBITS(A6),A0 ;POINT TO DSTBITS
_BITSTOMAP ;GET POINTER TO BIT/PIXMAP IN A0
MOVE.L A0,A1 ;SAVE IN A1
MOVE.L A3,D4 ;IS THEPORT NIL ?
BEQ.S NOTPORT ;YES, NOT TO THEPORT
BTST #0,D4 ;IS THEPORT ODD ?
BNE.S NOTPORT ;YES, NOT TO THEPORT
MOVE.L D4,A0 ;GET THEPORT
_PORTTOMAP ;CONVERT PORT TO BIT/PIXMAP
MOVE.L BASEADDR(A0),D4 ;GET PORTBITS.BASEADDR
CMP.L BASEADDR(A1),D4 ;IS DST BASEADDR SAME ?
BNE.S NOTPORT ;NO, NOT TO THEPORT
MOVE.L BOUNDS(A0),D4 ;GET PORT BOUNDS TOPLEFT
CMP.L BOUNDS(A1),D4 ;IS BOUNDS TOPLEFT SAME ?
BNE.S NOTPORT ;=>NO, NOT TO THE PORT
MOVE.L CLIPRGN(A3),D2 ;YES, CLIP TO CLIPRGN
MOVE.L VISRGN(A3),D3 ;AND TO VISRGN
NOTPORT MOVE.L DSTBITS(A6),A1 ;Pass DSTBITS (not derefed) <BAL 28May89>
JSR CMDevLoop ;AND DRAW THE IMAGE
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'CopyMask'
KopyMask PROC EXPORT
IMPORT PORTTOMAP,BITSTOMAP,CMDevLoop
;--------------------------------------------------------------
;
; PROCEDURE KopyMask(srcBits,maskBits,dstBits: BitMap;
; srcRect,maskRect,dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle *);
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE EQU 30 ;total bytes of params
SRCBITS EQU PARAMSIZE+8-4 ;long, addr of BitMap
MASKBITS EQU SRCBITS-4 ;long, addr of BitMap
DSTBITS EQU MASKBITS-4 ;long, addr of BitMap
SRCRECT EQU DSTBITS-4 ;long, addr of Rect
MASKRECT EQU SRCRECT-4 ;long, addr of Rect
DSTRECT EQU MASKRECT-4 ;long, addr of Rect
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
VARSIZE EQU -4
share LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE WORK REGISTERS FOR DEVLOOP
CLR.L -4(A6)
MOVE.L MASKBITS(A6), D0
BEQ @skip
MOVEA.L D0, A0
CMPI #$1, $20(A0)
BNE @skip
MOVEA.L $16(A6), A0
MOVEA.L $E(A6), A1
MOVE $4(A0), D0
SUB (A0), D0
SUB $4(A1), D0
ADD (A1), D0
BGT.B @L0
MOVE $6(A0), D0
SUB $2(A0), D0
SUB $6(A1), D0
ADD $2(A0), D0
BLE @skip
@L0 SUBQ #$4, SP
DC.W $AA18 ;_GetCTable
MOVE.L (SP)+, D3
BEQ @skip
SUBQ #$2, SP
PEA.L -4(A6)
MOVE #$2, -(SP)
PEA.L MASKRECT(A6)
MOVE.L D3, -(SP)
CLR.L -(SP)
PEA 4
MOVE.L #$160000,D0 ;_QDExtensions -> _NewGWorld
DC.W $AB1D
MOVE (SP)+, D4
BNE.B @L1
TST.L -4(A6)
BNE.B @L2
@L1 SUBQ #$2, SP
PEA.L -4(A6)
MOVE #$2, -(SP)
PEA.L MASKRECT(A6)
MOVE.L D3, -(SP)
CLR.L -(SP)
CLR.L -(SP)
MOVE.L #$160000,D0 ;_QDExtensions -> _NewGWorld
DC.W $AB1D
MOVE (SP)+, D4
@L2 MOVE.L D3, -(SP)
DC.W $AA24 ;_DisposCTable
TST D4
BNE.B @skip
MOVE.L -4(A6), D0
BEQ.B @skip
MOVEA.L D0, A3
SUBQ #$8, SP
PEA.L $4(SP)
PEA.L $4(SP)
MOVE.L #$80005,D0 ;_QDExtensions -> _GetGWorld
DC.W $AB1D
MOVE.L -4(A6), -(SP)
CLR.L -(SP)
MOVE.L #$80006,D0 ;_QDExtensions -> _SetGWorld
DC.W $AB1D
MOVE.L MASKBITS(A6), -(SP)
PEA.L $2(A3)
MOVE.L MASKRECT(A6), -(SP)
PEA.L $10(A3)
CLR -(SP)
CLR.L -(SP)
DC.W $A8EC ;_CopyBits
SUBQ #$2, SP
MOVE.L $2(A3), -(SP)
MOVE.L #$40001,D0 ;_QDExtensions -> _LockPixels
DC.W $AB1D
ADDQ #$2, SP
MOVEA.L $2(A3), A0
_HLock
MOVE.L (A0), MASKBITS(A6)
MOVE.L #$80005,D0 ;_QDExtensions -> _GetGWorld
DC.W $AB1D
@skip
; SET UP REGISTERS FOR CALLING CMDEVLOOP
MOVE.L DSTBITS(A6),A1 ;GET DST BIT/PIXMAP
MOVE.L MASKBITS(A6),D0 ;GET MASK BIT/PIXMAP
MOVE.L MASKRECT(A6),D1 ;GET MASK RECTANGLE
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;GET THE PORT IN A3 FOR DEVLOOP
MOVE.L WIDEOPEN(A4),D2 ;ASSUME NO CLIPPING FOR FIRST RGN
MOVE.L D2,D3 ;ASSUME NO CLIPPING FOR SECOND RGN
; PUSH PARAMETERS FOR CALLING CMDEVLOOP (SAME AS STDBITS)
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRC BIT/PIXMAP
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRC RECTANGLE
MOVE.L DSTRECT(A6),-(SP) ;PUSH DST RECTANGLE
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK ;WAS IT NIL ?
MOVE.L D2,(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK
;-----------------------------------------------------
;
; TEST IF DST IS TO THEPORT, (IF SO WE CLIP)
;
SRCOK MOVE.L DSTBITS(A6),A0 ;POINT TO DSTBITS
_BITSTOMAP ;GET POINTER TO BIT/PIXMAP IN A0
MOVE.L A0,A1 ;SAVE IN A1
MOVE.L A3,D4 ;IS THEPORT NIL ?
BEQ.S NOTPORT ;YES, NOT TO THEPORT
BTST #0,D4 ;IS THEPORT ODD ?
BNE.S NOTPORT ;YES, NOT TO THEPORT
MOVE.L D4,A0 ;GET THEPORT
_PORTTOMAP ;CONVERT PORT TO BIT/PIXMAP
MOVE.L BASEADDR(A0),D4 ;GET PORTBITS.BASEADDR
CMP.L BASEADDR(A1),D4 ;IS DST BASEADDR SAME ?
BNE.S NOTPORT ;NO, NOT TO THEPORT
MOVE.L BOUNDS(A0),D4 ;GET PORT BOUNDS TOPLEFT
CMP.L BOUNDS(A1),D4 ;IS BOUNDS TOPLEFT SAME ?
BNE.S NOTPORT ;=>NO, NOT TO THE PORT
MOVE.L CLIPRGN(A3),D2 ;YES, CLIP TO CLIPRGN
MOVE.L VISRGN(A3),D3 ;AND TO VISRGN
NOTPORT MOVE.L DSTBITS(A6),A1 ;Pass DSTBITS (not derefed) <BAL 28May89>
JSR CMDevLoop ;AND DRAW THE IMAGE
MOVE.L -4(A6),D0
BEQ.S @skipQDCall
MOVE.L D0,-(SP)
MOVE.L #$40004,D0 ;_QDExtensions -> _DisposeGWorld
DC.W $AB1D
@skipQDCall
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'KopyMask'
CMDevLoop PROC EXPORT
;---------------------------------------------------------------
;
; PROCEDURE CMDevLoop( VAR srcBits: BitMap;
; VAR srcRect: Rect;
; VAR dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle);
;
; This is a mock version of StdBits used for calling DevLoop
; for transfers to multiple screen devices.
; A4 = QUICKDRAW GLOBALS
; A3 = THEPORT
; A1 = DSTBITS
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 18
SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
SRCRECT EQU SRCBITS-4 ;LONG, ADDR OF RECT
DSTRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
; SRC DEVICE RECORDS STORED ON STACK
FLAG EQU 0 ;OFFSET TO FLAG
DEV EQU FLAG+2 ;OFFSET TO DEVICE
RECT EQU DEV+4 ;OFFSET TO RECT
SIZE EQU RECT+8 ;SIZE OF RECORD
SRCPIX EQU -(PMREC+CTREC+20) ;PIXMAP + COLOR TABLE
TEMPPIX EQU SRCPIX-PMREC ;PIXMAP
DSTBITS EQU TEMPPIX-4 ;DST BITMAP
GLOBALSRC EQU DSTBITS-8 ;GLOBAL COPY OF SRC RECT
GLOBALDST EQU GLOBALSRC-8 ;GLOBAL COPY OF DST RECT
SRCRECT1 EQU GLOBALDST-8 ;LOCAL COPY OF SRC RECT
DSTRECT1 EQU SRCRECT1-8 ;LOCAL COPY OF DST RECT (MUST FOLLOW SRCRECT1)
RECT1 EQU DSTRECT1-8 ;RESULT OF INTERSECTION
DEFSRC EQU RECT1-SIZE ;DEFAULT SRC RECORD
ENDSRC EQU DEFSRC-4 ;0 FOR TERMINATING SRC LIST
SRCDEV EQU ENDSRC-4 ;CURRENT SRC DEVICE RECORD
ENDDST EQU SRCDEV-4 ;0 FOR TERMINATING DST LIST
DSTDEV EQU ENDDST-4 ;CURRENT DST DEVICE
SRCLIST EQU DSTDEV-4 ;POINTER TO SORTED SRC RECT LIST
DSTLIST EQU SRCLIST-4 ;POINTER TO SORTED DST RECT LIST
SAVEDSP EQU DSTLIST-4 ;SAVED STACK POINTER
LASTSEED EQU SAVEDSP-4 ;LAST COLOR TABLE SEED
SAVEFG EQU LASTSEED-4 ;ORIGINAL FG COLOR
SAVEBK EQU SAVEFG-4 ;ORIGINAL BK COLOR
SAVEHILITE EQU SAVEBK-2 ;SAVED HILITE MODE FLAG
RGNA EQU SAVEHILITE-4 ;FIRST REGION FOR CLIPPING
RGNB EQU RGNA-4 ;SECOND REGION FOR CLIPPING
MASKBITS EQU RGNB-4 ;BITMAP FOR MASK
MASKRECT EQU MASKBITS-4 ;LONG, ADDR OF MASK RECT
VARSIZE EQU MASKRECT ;TOTAL SIZE OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STDBITS STACK FRAME
MOVE.L A1,DSTBITS(A6) ;SET UP DSTBITS
MOVE.L D0,MASKBITS(A6) ;SET UP MASKBITS
MOVE.L D1,MASKRECT(A6) ;SET UP MASKRECT
MOVE.L D2,RGNA(A6) ;SET FIRST REGION TO WIDEOPEN
MOVE.L D3,RGNB(A6) ;SET SECOND REGION TO WIDEOPEN
_BitsDevLoop ;DRAW TO ALL DEVICES
UNLINK PARAMSIZE,'GODEVLOO'
SeedFill PROC EXPORT
EXPORT CalcMask
;-------------------------------------------------------------------------
;
; PROCEDURE SeedFill(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER;
; seedH,seedV: INTEGER)
;
MOVE.L (SP)+,A0 ;pop return addr
MOVEQ #-1,D0 ;get a long of -1
MOVE.L D0,-(SP) ;push edge = all ones
BRA.S SHARE ;share common code
;-------------------------------------------------------------------------
;
; PROCEDURE CalcMask(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER);
;
CalcMask MOVE.L (SP)+,A0 ;pop return addr
MOVEQ #-1,D0 ;get a long of -1
MOVE.L D0,-(SP) ;push seed = (-1,-1)
CLR.L -(SP) ;push edge = zeros
SHARE MOVE.L A0,-(SP) ;restore return addr
;-------------------------------------------------------------------------
;
; LOCAL PROCEDURE MakeMask(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER;
; seedH,seedV: INTEGER;
; edge: LongInt);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE EQU 24
srcPtr EQU PARAMSIZE+8-4 ;long
dstPtr EQU srcPtr-4 ;long
srcRow EQU dstPtr-2 ;word
dstRow EQU srcRow-2 ;word
height EQU dstRow-2 ;word
words EQU height-2 ;word
seedH EQU words-2 ;word
seedV EQU seedH-2 ;word
edge EQU seedV-4 ;long
dstBump EQU -2 ;word
saveStk EQU dstBump-4 ;long
varSize EQU saveStk ;total locals
LINK A6,#varSize ;allocate stack frame
MOVEM.L D3-D7/A2-A4,-(SP) ;save regs
MOVE.L SP,saveStk(A6) ;save stack pointer
;
; prepare height and words for DBRA count. Quit if either <= 0.
;
MOVE words(A6),D5 ;get count of words
BLE GOHOME ;quit if words <= 0
SUB #1,D5 ;subtract 1 for DBRA count
SUB #1,height(A6) ;convert height to DBRA
BLT GOHOME ;quit if height <= 0
;
; init dst to all ones:
;
MOVE words(A6),D0 ;get # of words
ADD D0,D0 ;double for bytes
MOVE dstRow(A6),D1 ;get dstRow
SUB D0,D1 ;subtract bytes for dstBump
MOVE D1,dstBump(A6) ;save dstBump for later
MOVE.L dstPtr(A6),A2 ;point to dst
MOVEQ #-1,D0 ;get some black
MOVE height(A6),D3 ;init DBRA rowCount
BLACK1 MOVE D5,D2 ;init DBRA wordCount
BLACK2 MOVE D0,(A2)+ ;put a word of black
DBRA D2,BLACK2 ;loop all words in row
ADD D1,A2 ;bump to next row
DBRA D3,BLACK1 ;loop height rows
;
; clear one dst pixel at seedH,seedV
;
MOVE seedV(A6),D0 ;get seed vert coord
BLT.S NOSEED ;skip if neg (no seed)
MULU dstRow(A6),D0 ;mul times dst row
MOVE.L dstPtr(A6),A0 ;point to dst
ADD.L D0,A0 ;add vertical offset <EHB 28-Oct-85>
MOVE seedH(A6),D0 ;get seed horiz coord
MOVE D0,D1 ;copy seedH
ASR #3,D0 ;div by 8 for byte
NOT D1 ;invert bit number
BCLR D1,0(A0,D0) ;clear seed pixel
NOSEED
;
; allocate a scanline buffer of ones or zeros on the stack:
;
MOVE.L edge(A6),D6 ;get zero or all ones
MOVE D5,D1 ;get longCount
NEXTBUF MOVE D6,-(SP) ;write a word of ones or zeros
DBRA D1,NEXTBUF ;loop all words
MOVE.L srcPtr(A6),A0 ;point to top of src
MOVE.L dstPtr(A6),A2 ;point to top of dst
st d7 ;set dirty flag to force <KON 24JAN91>
bra.s FirstPass ;search up and down <KON 24JAN91>
NXTPASS SF D7 ;clear dirty flag
FirstPass
MOVE height(A6),D4 ;get DBRA rowCount
MOVE.L SP,A1 ;point dst above to edgeBuf
;
; smear dst zeros down and to the right, smear limited by src.
;
NEXTROW MOVE.L D6,D1 ;init prev dst to edge
MOVE D5,D3 ;get DBRA wordCount
RNEXT MOVE (A2),D1 ;get dst word
BNE.S RDSTOK ;is it already zero ?
ADD #2,A0 ;yes, bump srcPtr
ADD #2,A1 ;bump dstAbove ptr
ADD #2,A2 ;bump dst ptr
SWAP D1 ;put prev dst in hi word
DBRA D3,RNEXT ;loop all words in row
BRA.S RDONE ;and continue below
RDSTOK MOVE (A0)+,D2 ;get src word
AND (A1)+,D1 ;smear zeros down
OR D2,D1 ;limit vertical smear by src
BRA.S RSTART ;go to loop start
RMORE MOVE D0,D1 ;update dst
RSTART MOVE.L D1,D0 ;copy dst and prev dst word
LSR.L #1,D0 ;shift right with carry from prev
AND D1,D0 ;smear zeros to the right
OR D2,D0 ;limit smear by src
CMP D1,D0 ;any changes ?
BNE RMORE ;yes, keep smearing
CMP (A2),D1 ;has dst changed ?
BEQ.S RSAME ;no, leave it alone
ST D7 ;yes, set dirty flag
RSAME MOVE D1,(A2)+ ;write dst to memory
SWAP D1 ;put prev dst in hi word
DBRA D3,RNEXT ;loop all words in row
RDONE
;
; smear dst zeros down and to the left, smear limited by src.
;
LSMEAR MOVE.L D6,D1 ;init prev dst to edge
MOVE D5,D3 ;get DBRA wordCount
LNEXT MOVE -(A2),D1 ;get dst word
BNE.S LDSTOK ;is dst already zero ?
SUB #2,A0 ;yes, just bump srcPtr
SUB #2,A1 ;bump dstAbove ptr
SWAP D1 ;put prev dst in hi word
DBRA D3,LNEXT ;loop all words in row
BRA.S LDONE ;and continue
LDSTOK MOVE -(A0),D2 ;get src word
AND -(A1),D1 ;smear zeros down
OR D2,D1 ;limit vertical smear by src
BRA.S LSTART ;go to loop start
LMORE MOVE D0,D1 ;update dst
LSTART MOVE.L D1,D0 ;copy dst and prev dst word
ROL.L #1,D0 ;shift left with carry from prev
AND D1,D0 ;smear zeros to the left
OR D2,D0 ;limit smear by src
CMP D1,D0 ;any changes ?
BNE LMORE ;yes, keep smearing
CMP (A2),D1 ;has dst changed ?
BEQ.S LSAME ;no, leave it alone
ST D7 ;yes, set dirty flag
MOVE D1,(A2) ;write dst to memory
LSAME SWAP D1 ;put prev dst in hi word
DBRA D3,LNEXT ;loop all words in row
LDONE
;
; bump three pointers down and loop for height scanlines
;
ADD srcRow(A6),A0 ;bump srcPtr down a row
ADD dstRow(A6),A2 ;bump dstPtr down a row
MOVE.L A2,A1 ;copy dstPtr
SUB dstRow(A6),A1 ;point to dst above
DBRA D4,NEXTROW ;loop all rows
;
; switch directions, adjust pointers, and loop till no change
;
NEG srcRow(A6) ;reverse src bump
NEG dstRow(A6) ;reverse dst bump
ADD srcRow(A6),A0 ;offset first src scanline
ADD dstRow(A6),A2 ;offset first dst scanline
TST.B D7 ;did anything change this pass ?
BNE NXTPASS ;yes go for another pass
;
; if seedFill, then invert dst
;
TST D6 ;is edge = black ?
BPL.S GOHOME ;no, we're done
MOVE dstBump(A6),D1 ;get dstBump
MOVE.L dstPtr(A6),A2 ;point to dst
MOVE height(A6),D3 ;init DBRA rowCount
INVERT1 MOVE D5,D2 ;init DBRA wordCount
INVERT2 NOT (A2)+ ;invert a word of dst
DBRA D2,INVERT2 ;loop all words in row
ADD D1,A2 ;bump to next row
DBRA D3,INVERT1 ;loop height rows
GOHOME MOVE.L saveStk(A6),SP ;restore stack pointer
MOVEM.L (SP)+,D3-D7/A2-A4 ;restore regs
UNLINK PARAMSIZE,'SEEDFILL'
ScrollRect PROC EXPORT
;---------------------------------------------------------------------
;
; PROCEDURE ScrollRect(srcRect: Rect; dh,dv: INTEGER; updateRgn: RgnHandle);
;
; Scroll a rectangular block of bits, erase and return an update region
; If the update region is nil, don't erase it.
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
; as taken verbatim from QDciPatchROM.a <sm 6/9/92>stb
PARAMSIZE EQU 12 ;TOTAL BYTES OF PARAMS
SRCRECT EQU PARAMSIZE+8-4 ;LONG, ADDR OF RECT
DH EQU SRCRECT-2 ;WORD
DV EQU DH-2 ;WORD
THEUPDATERGN EQU DV-4 ;LONG, RGNHANDLE
DSTRECT EQU -8 ;RECT
tempRect1 EQU DSTRECT-8 ;rect
tempRect2 EQU tempRect1-8 ;rect
globalSrc EQU tempRect2-8 ;rect
VARSIZE EQU globalSrc ;TOTAL LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D6-D7/A3-A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
MOVE.L PICSAVE(A3),-(SP) ;SAVE PICSAVE HANDLE
CLR.L PICSAVE(A3) ;DON'T RECORD TO PICTURES
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT ABORT ;YES, QUIT FAST
TST.L DV(A6) ;ARE DH AND DV BOTH 0 ?
BEQ ABORT ;YES, QUIT FAST
; SAVE FOREGROUND AND BACKGROUND COLORS, AND SET TO BLACK AND WHITE FOR SCROLL
sub.l #ColorSpecSize,sp ;make room for an ColorSpec <DDG 28Jan90>
move.l sp,-(sp) ;point to this record
_SaveFore
sub.l #ColorSpecSize,sp ;make room for an ColorSpec <DDG 28Jan90>
move.l sp,-(sp) ;point to this record
_SaveBack
MOVE.L #BLACKCOLOR,-(SP) ;PUSH BLACK
_FORECOLOR ;AND SET FOREGROUND COLOR TO BLACK
MOVE.L #WHITECOLOR,-(SP) ;PUSH WHITE
_BACKCOLOR ;AND SET BACKGROUND COLOR TO BLACK
; ALLOCATE TEMP REGIONS FOR CALCULATIONS
SUB #8,SP ;ROOM FOR 2 FCN RESULT
_NEWRGN ;ALLOCATE SRCRGN
MOVE.L (SP)+,D7 ;GET SRCRGN IN D7
_NEWRGN ;ALLOCATE DSTRGN
MOVE.L (SP)+,D6 ;GET DSTRGN IN D6
; srcRgn := srcRect SECT visRgn SECT clipRgn
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
_RECTRGN ;RectRgn(srcRgn,srcRect);
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN
MOVE.L D7,-(SP) ;PUSH SRCRGN
_SECTRGN ;SectRgn(srcRgn,visRgn,srcRgn);
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN
MOVE.L D7,-(SP) ;PUSH SRCRGN
_SECTRGN ;SectRgn(srcRgn,clipRgn,srcRgn);
; dstRgn := offset srcRgn
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L D6,-(SP) ;PUSH DSTRGN
_COPYRGN ;CopyRgn(srcRgn,dstRgn);
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L DV(A6),-(SP) ;PUSH DH,DV
_OFSETRGN ;OffsetRgn(dstRgn,dh,dv);
; DSTRECT := OFFSETRECT(SRCRECT,DH,DV)
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE.L (A0)+,DSTRECT(A6) ;COPY SRCRECT INTO DSTRECT
MOVE.L (A0)+,DSTRECT+4(A6)
MOVE.L DV(A6),D0 ;GET DH,DV
ADD D0,DSTRECT+LEFT(A6) ;OFFSET DSTRECT (DH,DV)
ADD D0,DSTRECT+RIGHT(A6)
SWAP D0 ;GET DV IN LO WORD
ADD D0,DSTRECT+TOP(A6)
ADD D0,DSTRECT+BOTTOM(A6)
; MASKRGN := SECTRGN(SRCRGN,DSTRGN)
; NOTE: UPDATERGN CAN'T BE USED AS MASKRGN BECAUSE IF UPDATERGN = VISRGN
; THEN NOTHING WILL BE SCROLLED
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L D6,-(SP) ;KEEP MASKRGN
_SECTRGN ;SectRgn(srcRgn,dstRgn,maskRgn);
;----------------------------------------------------------------------------------------------------
;
; Now we check for multiple devices and do the correct things here <DDG 28Jan90>
;
move.l DeviceList,a0 ;get the head of the device list <DDG 28Jan90>
move.l (a0),a0 ;deref it
move.l GDNextGD(a0),d0 ;check the next device field. If it's zero
beq oneDevice ;..then goto one device
;
; Allocate extra region used by cutOutDevices
;
movem.l d5/a2,-(sp) ;save reg.
clr.l -(sp) ;make room for result
_NewRgn ;allocate another RGN <DDG 28Jan90>
move.l (sp)+,d5 ;put our new region in d5
;
; convert the source rect to global coordinates
;
move.l srcRect(a6),a1 ;point to our source rect
lea globalSrc(a6),a0 ;point to out global source rect
move.l (a1)+,topleft(a0) ;copy srcRect.topleft
move.l (a1)+,botright(a0) ;copy srcRect.botRight
pea topleft(a0) ;convert the global rect to global coordinates
_LocalToGlobal
pea botright(a0)
_LocalToGlobal
;
; Start scanning through the device list
;
move.l DeviceList,a2 ;get the device list header into A2
@loop move.l (a2),a4 ;deref the current device list handle
tst GDFlags(a4) ;is the device active ?
bpl.s @next ;=>no, skip to the next device
clr.b -(sp) ;make space for boolean result
pea globalSrc(a6) ;pointer to the SrcRect in global coordinates
pea GDRect(a4) ;pointer to the device rect
pea tempRect1(a6) ;pointer to the result
_SectRect ;get the intersection
tst.b (sp)+ ;if they didn't intersect at all, then skip to
beq.s @next ;..the next device
move.l DV(a6),d0 ;get DV into high word and DH into low word
add d0,tempRect1+left(a6)
add d0,tempRect1+right(a6)
swap d0 ;get DV into the low word
add d0,tempRect1+top(a6)
add d0,tempRect1+bottom(a6)
move.l GDPMap(a4),a0 ;get handle to the source pixMap
move.l (a0),a0 ;deref it
move.l pmTable(a0),a0 ;get handle to source color table
move.l (a0),a0 ;deref it
move.l ctSeed(a0),d1 ;get color table seed into d1
bsr cutOutDevices ;this cuts out different devices from d5
@next move.l (a2),a4 ;deref the current device list handle
move.l GDNextGD(a4),d0 ;get the next device handle into D0
move.l d0,a2 ;move it to our current handle. If it's NOT null
bne.s @loop ;..then loop back.
MOVE.L D5,A0 ;GET tmp region used by cutOutDevices
_DISPOSHANDLE ;DISCARD IT
movem.l (sp)+,d5/a2 ;restore d5
;----------------------------------------------------------------------------------------------------
oneDevice
; Scroll the rect using CopyBits
PEA PORTBITS(A3) ;PUSH SRCBITS
MOVE.L (SP),-(SP) ;PUSH DSTBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
PEA DSTRECT(A6) ;PUSH DSTRECT
CLR -(SP) ;PUSH MODE = SRCCOPY
MOVE.L D6,-(SP) ;PUSH MASK REGION
_COPYBITS ;COPY THE BITS
; RESTORE FOREGROUND AND BACKGROUND COLORS
move.l sp,-(sp) ;point to the saved back color and restore it
_RestoreBack ; <DDG 28Jan90>
add.l #ColorSpecSize,sp ;strip the ColorSpec off the stack
move.l sp,-(sp) ;point to the saved back color and restore it
_RestoreFore
add.l #ColorSpecSize,sp ;strip the ColorSpec off the stack
; IF UPDATERGN NOT NIL, COMPUTE UPDATERGN := DIFFRGN(SRCRGN,DSTRGN) AND ERASE
MOVE.L THEUPDATERGN(A6),D0 ;GET THEUPDATERGN
BEQ.S NOUDR ;=>NO UPDATE RGN
MOVE.L D0,-(SP) ;PUSH UPDATERGN FOR ERASE
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L D0,-(SP) ;PUSH UPDATERGN
_DIFFRGN ;DiffRgn(srcRgn,dstRgn,updateRgn);
_ERASERGN ;AND ERASE UPDATE REGION
NOUDR MOVE.L D7,A0 ;GET SRCRGN
_DISPOSHANDLE ;DISCARD IT
MOVE.L D6,A0 ;GET DSTRGN
_DISPOSHANDLE ;DISCARD IT
BRA.S DONE
ABORT MOVE.L THEUPDATERGN(A6),D0 ;IS THERE AN UPDATE REGION?
BEQ.S DONE ;=>NO, DON'T EMPTY IT
MOVE.L D0,-(SP) ;PUSH UPDATERGN HANDLE
_SETEMPTYRGN ;SET IT TO EMPTY
DONE MOVE.L (SP)+,PICSAVE(A3) ;RESTORE PICSAVE HANDLE
MOVEM.L (SP)+,D6-D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'SCROLLRE'
;----------------------------------------------------------------------------------------------------
cutOutDevices
move.l DeviceList,a1 ;get the device list header into A1
@loop move.l (a1),a0 ;deref the current device list handle
tst GDFlags(a0) ;is the device active ?
bpl @next ;=>no, skip to the next device
move.l GDPMap(a0),a0 ;get handle to the source pixMap
move.l (a0),a0 ;deref it
move.l pmTable(a0),a0 ;get handle to source color table
move.l (a0),a0 ;deref it
cmp.l ctSeed(a0),d1 ;do the color tables seeds match ?
beq @next
movem.l d1/a1-a3,-(sp) ;save our scratch registers
clr.b -(sp) ;make space for boolean result
pea tempRect1(a6) ;pointer to the SrcRect in global coordinates
move.l (a1),a0 ;deref the current device list handle
pea GDRect(a0) ;pointer to the device rect
pea tempRect2(a6) ;pointer to the result
_SectRect ;get the intersection
tst.b (sp)+ ;if they didn't intersect at all, then skip to
beq @skip ;..the next device
move.l (a1),a0
move.l GDPMap(a0),a0
move.l (a0),a0
move.l pmTable(a0),a0
move.l (a0),a0
move.l (DeviceList),a2
@again move.l (a2),a2
move.l GDPMap(a2),a3
move.l (a3),a3
move.l pmTable(a3),a3
move.l (a3),a3
move.l (a3),d0
cmp.l (a0),d0
bne @done
sub.l #8,sp
clr.b -(sp)
pea.l tempRect1(a6)
pea.l $22(a2)
pea.l $a(sp)
_SectRect
tst.b (sp)+
add.l #8,sp
bne @skip
@done move.l GDNextGD(a2),d0
move.l d0,a2
bne.s @again
lea tempRect2(a6),a0 ;point to our temp rect
pea topleft(a0) ;convert the temp rect back to local coordinates
_GlobalToLocal
pea botright(a0)
_GlobalToLocal
move.l d5,-(sp) ;convert tempRect2 into a region
pea tempRect2(a6)
_RectRgn
move.l d6,-(sp) ;subtract this little invalid rect out of the
move.l d5,-(sp) ;..mask region.
move.l d6,-(sp)
_DiffRgn
@skip movem.l (sp)+,d1/a1-a3 ;restore our scratch registers
@next move.l (a1),a0 ;deref the current device list handle
move.l GDNextGD(a0),d0 ;get the next device handle into D0
move.l d0,a1 ;move it to our current handle. If it's NOT null
bne.s @loop ;..then loop back.
rts
;----------------------------------------------------------------------------------------------------
ENDP
PackBits PROC EXPORT
EXPORT UnpackBits
;---------------------------------------------------------------------
;
; PROCEDURE PackBits(VAR srcPtr,dstPtr: Ptr; srcBytes: INTEGER);
;
; Packs one scanline of data, compressing equal bytes.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are shared with UnpackBits
;
PARAMSIZE EQU 10 ;TOTAL BYTES OF PARAMS
SRCPTR EQU PARAMSIZE+4-4 ;LONG, VAR
DSTPTR EQU SRCPTR-4 ;LONG,VAR
SRCBYTES EQU DSTPTR-2 ;WORD
DSTBYTES EQU SRCBYTES ;ALIAS
MOVEM.L D3-D4/A2,-(SP) ;SAVE REGS
MOVE #128,D4 ;GET USEFUL VALUE
MOVE.L SRCPTR+12(SP),A0 ;GET VAR ADDR
MOVE.L (A0),A0 ;GET SRCPTR ITSELF
MOVE.L DSTPTR+12(SP),A1 ;GET VAR ADDR
MOVE.L (A1),A1 ;GET DSTPTR ITSELF
MOVE SRCBYTES+12(SP),D3 ;GET SRCBYTES
SUB #1,D3 ;INIT SRC DBRA COUNT
BLT.S DONE ;QUIT IF SRCBYTES <= 0
GoStart MOVE.B (A0)+,D0 ;GET FIRST BYTE OF SRC
BRA.S START ;AND GO TO LOOP START
FILLOP MOVE.B -1(A0),D0 ;PUT SRCDATA IN DO
SUB A0,D2 ;COMPUTE FILLOP
ADD D2,D3 ;UPDATE BYTECOUNT
ADD #1,D2 ;-2..-128 -> -1..-127
MOVE.B D2,(A2) ;STORE FILLOP
START MOVEQ #127,D1 ;GET MAX BYTECOUNT-1 FOR A RUN
CMP D4,D3 ;THAT MANY BYTES LEFT?
BGE.S @1 ;=>YES, DO CHUNK OF 128
MOVE D3,D1 ;ELSE DO REMAINING BYTES
@1 MOVE A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
CMP.B (A0),D0 ;IS NEXT SRC THE SAME ?
BNE.S DOCOPY ;NO, USE COPY LOOP
CMP.B 1(A0),D0 ;THREE IN A ROW ?
BNE.S DOCOPY ;NO, USE COPY LOOP
BRA.S DOFILL ;YES, USE FILL LOOP
NXTCOPY MOVE.B (A0)+,D0 ;GET BYTE OF SRC
CMP.B (A0),D0 ;IS THE NEXT THE SAME ?
BNE.S DOCOPY ;NO, CONTINUE
CMP.B 1(A0),D0 ;THREE IN A ROW ?
BEQ.S COPYOP ;YES, END OF COPY RUN
DOCOPY MOVE.B D0,(A1)+ ;COPY DATA TO DST
DBRA D1,NXTCOPY ;AND LOOP FOR MORE
ENDCOPY SUB A0,D2 ;COMPUTE COPYOP
NEG D2 ;NEGATE ONLY
MOVE.B D2,(A2) ;INSTALL COPYOP
SUB D4,D3 ;SUBTRACT NEXT CHUNK
BPL.S GoStart ;=>MORE TO DO, CONTINUE
BRA.S DONE ;AND QUIT
COPYOP TST D1 ;IS THIS THE LAST SRC BYTE ?
BEQ DOCOPY ;YES, FINISH OFF COPY RUN
SUB A0,D2 ;COMPUTE COPYOP
ADD D2,D3 ;UPDATE BYTECOUNT
NOT D2 ;NEGATE AND SUBTRACT 1
MOVE.B D2,(A2) ;STORE COPYOP
MOVEQ #127,D1 ;GET MAX BYTECOUNT FOR A RUN
CMP D4,D3 ;THAT MANY BYTES LEFT?
BGE.S @1 ;=>YES, DO CHUNK OF 128
MOVE D3,D1 ;ELSE DO REMAINING BYTES
@1 MOVE.L A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
DOFILL MOVE.B D0,(A1)+ ;COPY THE DATA BYTE
NXTFILL CMP.B (A0)+,D0 ;IS NEXT BYTE THE SAME ?
DBNE D1,NXTFILL ;LOOP TILL NOT SAME OR END SRC
BEQ.S ENDFILL ;BRANCH IF SRC EXHAUSTED
SUB #1,D1 ;COMPENSATE FOR DBNE DIDNT SUB
BGE FILLOP ;BR IF SRC NOT EXHAUSTED
ENDFILL SUB #1,A0 ;BACK UP FOR LAST BYTE COMPARED
SUB A0,D2 ;COMPUTE FILLOP
MOVE.B D2,(A2) ;INSTALL FILLOP
SUB D4,D3 ;SUBTRACT NEXT CHUNK
BPL.S GoStart ;=>MORE TO DO, CONTINUE
DONE CLR.L D0 ;GET READY FOR WORD
MOVE SRCBYTES+12(SP),D0 ;GET SRCBYTES
MOVE.L SRCPTR+12(SP),A0 ;GET VAR ADDR OF SRCPTR
ADD.L D0,(A0) ;BUMP SRCPTR
MOVE.L DSTPTR+12(SP),A2 ;GET VAR ADDR OF DSTPTR
MOVE.L A1,(A2) ;UPDATE DSTPTR
MOVEM.L (SP)+,D3-D4/A2 ;RESTORE REGS
SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD #PARAMSIZE,SP ;STRIP PARAMS
JMP (A0) ;AND RETURN
;--------------------------------------------------------
;
; PROCEDURE UnpackBits(VAR srcPtr,dstPtr: Ptr; dstBytes: INTEGER);
;
; Unpacks one scanline of data, as compressed by PackBits.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are the same as PackBits!
;
UnpackBits
MOVE.L SRCPTR(SP),A0 ;GET ADDR OF SRCPTR
MOVE.L (A0),A0 ;GET SRCPTR ITSELF
MOVE.L DSTPTR(SP),A1 ;GET ADDR OF DSTPTR
MOVE.L (A1),A1 ;GET DSTPTR ITSELF
MOVE DSTBYTES(SP),D2 ;GET DSTBYTES
EXT.L D2 ;MAKE IT LONG
ADD.L A1,D2 ;LIMIT := DSTPTR + BYTECOUNT
BRA.S @3 ;GO TO LOOP START
@1 EXT.W D1 ;CLEAR HI BYTE OF COUNT
@2 MOVE.B (A0)+,(A1)+ ;COPY A BYTE OF DATA
DBRA D1,@2 ;LOOP ALL COPY BYTES
@3 CMP.L D2,A1 ;IS DSTPTR >= LIMIT ?
BHS.S @5 ;YES, WE'RE DONE
MOVE.B (A0)+,D1 ;NO, GET OPCODE
BPL.S @1 ;0..127 --> COPY 1..128 BYTES
NEG.B D1 ;-1..-127 --> FILL 2..128 BYTES
BVS.S @3 ;IGNORE $80 FOR BACKWARD COMPAT
EXT.W D1 ;CLEAR HI BYTE OF COUNT
MOVE.B (A0)+,D0 ;GET FILL DATA BYTE
@4 MOVE.B D0,(A1)+ ;COPY IT TO DST
DBRA D1,@4 ;LOOP ALL FILL BYTES
BRA.S @3 ;THEN GET NEXT OPCODE
@5 MOVE.L A0,D0 ;STASH SRCPTR
MOVE.L SRCPTR(SP),A0 ;GET VAR ADDR
MOVE.L D0,(A0) ;UPDATE VAR SRCPTR
MOVE.L DSTPTR(SP),A0 ;GET VAR ADDR
MOVE.L A1,(A0) ;UPDATE VAR DSTPTR
BRA.S SHARE
PackWords PROC EXPORT
EXPORT UnpackWords
;---------------------------------------------------------------------
;
; PROCEDURE PackWords(VAR srcPtr,dstPtr: Ptr; srcBytes: INTEGER);
;
; Packs one scanline of data, compressing equal words.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are shared with UnpackWords
;
PARAMSIZE EQU 10 ;TOTAL BYTES OF PARAMS
SRCPTR EQU PARAMSIZE+4-4 ;LONG, VAR
DSTPTR EQU SRCPTR-4 ;LONG,VAR
SRCBYTES EQU DSTPTR-2 ;WORD
DSTBYTES EQU SRCBYTES ;ALIAS
MOVEM.L D3-D4/A2,-(SP) ;SAVE REGS
MOVE #128,D4 ;GET USEFUL VALUE
MOVE.L SRCPTR+12(SP),A0 ;GET VAR ADDR
MOVE.L (A0),A0 ;GET SRCPTR ITSELF
MOVE.L DSTPTR+12(SP),A1 ;GET VAR ADDR
MOVE.L (A1),A1 ;GET DSTPTR ITSELF
MOVE SRCBYTES+12(SP),D3 ;GET SRCBYTES
lsr.w #1,d3 ;make in to word count <BAL 25Mar89>
SUB #1,D3 ;INIT SRC DBRA COUNT
BLT DONE ;QUIT IF SRCBYTES <= 0
GoStart MOVE.w (A0)+,D0 ;GET FIRST word OF SRC <BAL 25Mar89>
BRA.S START ;AND GO TO LOOP START
FILLOP MOVE.w -2(A0),D0 ;PUT SRCDATA IN DO <BAL 25Mar89>
SUB A0,D2 ;COMPUTE FILLOP
asr.w #1,d2 ;make into word cnt
ADD D2,D3 ;UPDATE wordCOUNT
ADD #1,D2 ;-2..-128 -> -1..-127
MOVE.B D2,(A2) ;STORE FILLOP
START MOVEQ #127,D1 ;GET MAX wordCOUNT-1 FOR A RUN
CMP D4,D3 ;THAT MANY words LEFT?
BGE.S @1 ;=>YES, DO CHUNK OF 128
MOVE D3,D1 ;ELSE DO REMAINING BYTES
@1 MOVE A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
CMP.w (A0),D0 ;IS NEXT SRC THE SAME ? <BAL 25Mar89>
BNE.S DOCOPY ;NO, USE COPY LOOP
CMP.w 2(A0),D0 ;THREE IN A ROW ? <BAL 25Mar89>
BNE.S DOCOPY ;NO, USE COPY LOOP
BRA.S DOFILL ;YES, USE FILL LOOP
NXTCOPY MOVE.w (A0)+,D0 ;GET word OF SRC <BAL 25Mar89>
CMP.w (A0),D0 ;IS THE NEXT THE SAME ? <BAL 25Mar89>
BNE.S DOCOPY ;NO, CONTINUE
CMP.w 2(A0),D0 ;THREE IN A ROW ? <BAL 25Mar89>
BEQ.S COPYOP ;YES, END OF COPY RUN
DOCOPY MOVE.w D0,(A1)+ ;COPY DATA TO DST <BAL 25Mar89>
DBRA D1,NXTCOPY ;AND LOOP FOR MORE
ENDCOPY SUB A0,D2 ;COMPUTE COPYOP
NEG D2 ;NEGATE ONLY
asr.w #1,d2 ;make word count <BAL 25Mar89>
MOVE.B D2,(A2) ;INSTALL COPYOP
SUB D4,D3 ;SUBTRACT NEXT CHUNK
BPL.S GoStart ;=>MORE TO DO, CONTINUE
BRA.S DONE ;AND QUIT
COPYOP TST D1 ;IS THIS THE LAST SRC BYTE ?
BEQ DOCOPY ;YES, FINISH OFF COPY RUN
SUB A0,D2 ;COMPUTE COPYOP
asr.w #1,d2 ;make word count <BAL 25Mar89>
ADD D2,D3 ;UPDATE BYTECOUNT
NOT D2 ;NEGATE AND SUBTRACT 1
MOVE.B D2,(A2) ;STORE COPYOP
MOVEQ #127,D1 ;GET MAX BYTECOUNT FOR A RUN
CMP D4,D3 ;THAT MANY BYTES LEFT?
BGE.S @1 ;=>YES, DO CHUNK OF 128
MOVE D3,D1 ;ELSE DO REMAINING BYTES
@1 MOVE.L A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
DOFILL MOVE.w D0,(A1)+ ;COPY THE DATA word <BAL 25Mar89>
NXTFILL CMP.w (A0)+,D0 ;IS NEXT word THE SAME ? <BAL 25Mar89>
DBNE D1,NXTFILL ;LOOP TILL NOT SAME OR END SRC
BEQ.S ENDFILL ;BRANCH IF SRC EXHAUSTED
SUB #1,D1 ;COMPENSATE FOR DBNE DIDNT SUB
BGE FILLOP ;BR IF SRC NOT EXHAUSTED
ENDFILL SUB #2,A0 ;BACK UP FOR LAST word COMPARED <BAL 25Mar89>
SUB A0,D2 ;COMPUTE FILLOP
asr.w #1,d2 ;make word count <BAL 25Mar89>
MOVE.B D2,(A2) ;INSTALL FILLOP
SUB D4,D3 ;SUBTRACT NEXT CHUNK
BPL.S GoStart ;=>MORE TO DO, CONTINUE
DONE CLR.L D0 ;GET READY FOR WORD
MOVE SRCBYTES+12(SP),D0 ;GET SRCBYTES
MOVE.L SRCPTR+12(SP),A0 ;GET VAR ADDR OF SRCPTR
ADD.L D0,(A0) ;BUMP SRCPTR
MOVE.L DSTPTR+12(SP),A2 ;GET VAR ADDR OF DSTPTR
MOVE.L A1,(A2) ;UPDATE DSTPTR
MOVEM.L (SP)+,D3-D4/A2 ;RESTORE REGS
SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD #PARAMSIZE,SP ;STRIP PARAMS
JMP (A0) ;AND RETURN
;--------------------------------------------------------
;
; PROCEDURE UnpackWords(VAR srcPtr,dstPtr: Ptr; dstBytes: INTEGER);
;
; Unpacks one scanline of data, as compressed by PackWords.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are the same as PackWords!
;
UnpackWords
MOVE.L SRCPTR(SP),A0 ;GET ADDR OF SRCPTR
MOVE.L (A0),A0 ;GET SRCPTR ITSELF
MOVE.L DSTPTR(SP),A1 ;GET ADDR OF DSTPTR
MOVE.L (A1),A1 ;GET DSTPTR ITSELF
MOVE DSTBYTES(SP),D2 ;GET DSTBYTES
EXT.L D2 ;MAKE IT LONG
ADD.L A1,D2 ;LIMIT := DSTPTR + BYTECOUNT
BRA.S @3 ;GO TO LOOP START
@1 EXT.W D1 ;CLEAR HI BYTE OF COUNT
@2 MOVE.w (A0)+,(A1)+ ;COPY A word OF DATA <BAL 25Mar89>
DBRA D1,@2 ;LOOP ALL COPY words
@3 CMP.L D2,A1 ;IS DSTPTR >= LIMIT ?
BHS.S @5 ;YES, WE'RE DONE
MOVE.B (A0)+,D1 ;NO, GET OPCODE
BPL.S @1 ;0..127 --> COPY 1..128 BYTES
NEG.B D1 ;-1..-127 --> FILL 2..128 BYTES
BVS.S @3 ;IGNORE $80 FOR BACKWARD COMPAT
EXT.W D1 ;CLEAR HI BYTE OF COUNT
MOVE.w (A0)+,D0 ;GET FILL DATA word <BAL 25Mar89>
@4 MOVE.w D0,(A1)+ ;COPY IT TO DST <BAL 25Mar89>
DBRA D1,@4 ;LOOP ALL FILL words
BRA.S @3 ;THEN GET NEXT OPCODE
@5 MOVE.L A0,D0 ;STASH SRCPTR
MOVE.L SRCPTR(SP),A0 ;GET VAR ADDR
MOVE.L D0,(A0) ;UPDATE VAR SRCPTR
MOVE.L DSTPTR(SP),A0 ;GET VAR ADDR
MOVE.L A1,(A0) ;UPDATE VAR DSTPTR
BRA.S SHARE
ENDPROC