; ; File: BitMaps.a ; ; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32 ; so they can conditionalized out of the build. ; 6/11/92 stb 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 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 ;---------------------------------------------------- ; ; 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? Bne.s doScreen ;Yes, convert it tst.b d6 ;is source a bitmap? bne notScrn ;YES, don't convert tst.b OldPic(a6) ;is dst old port? beq notScrn ;No, then don't convert source bra doConvert doScreen IF 1 THEN ;Can't optimize if screen needs 32-bit addressing ; ;---------------------------------------------------- ; 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? 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. 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 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 move.l d0,theGDevice ;set up offscreen GDevice 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 ;---------------------------------------------------- ; ; 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? 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? beq.s @NoDither ; move.w #$40,(sp) ;set dither mode @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 ;---------------------------------------------------- ; ; 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 ;---------------------------------------------------- ; ; 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? beq.s @PackOK ;no, don't need to adjust packType CMP #16,SRCPIX+PIXELSIZE(A6) ;16 bit/pixel? bne.s @pack32 ;no, check 32 bit/pixel packing types move #3,(a0) ;use only supported type bra.s @PackOK @pack32 cmp #2,(a0) ;drop pad byte only? beq.s @PackOK ;yes, don't need to adjust packType move #4,(a0) ;replace with only remaining supported packType @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> move.l d0, -(SP) ;PUSH CTABHANDLE <20> 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. ; 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 move #MinTableSize,-(sp) ;GET SIZE IN ENTRIES jsr PutPicData ;ADD TO THEPIC 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 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) ; ; <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. ; ; tst.b d5 ;are both src and destination the screen? beq.s @cont ;=>NO, Don't check for overlap <26> cmp.l SRCDEVICE,d1 ;are src and destination the same device? 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 ; ; 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. movem.l d1/a1,-(sp) ;save SUBQ #6,SP ;MAKE ROOM FOR A COLOR RECORD CLR.L -(SP) ;CLEAR INDEX, FLAGS WORDS 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 PEA 4(SP) ;POINT AT RECORD MOVE.L (SP),-(SP) ;AND AGAIN FOR GETFC _GETBACKCOLOR ;GET THE BACKGROUND COLOR _RGBBACKCOLOR ;SET THE BACKGROUND COLOR ADD #10,SP ;STRIP THE RECORD 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) CLR.L -(SP) ;NO MASK MOVE.L DSTBITS(A6),-(SP) ;PUSH DSTBITS (not derefed) 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) MOVE.L DSTBITS(A6),A1 ;Pass DSTBITS (not derefed) 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 ; ; 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) 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) 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 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 bra.s FirstPass ;search up and down 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 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 move.l sp,-(sp) ;point to this record _SaveFore sub.l #ColorSpecSize,sp ;make room for an ColorSpec 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 ; move.l DeviceList,a0 ;get the head of the device list 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 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 ; 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 SUB #1,D3 ;INIT SRC DBRA COUNT BLT DONE ;QUIT IF SRCBYTES <= 0 GoStart MOVE.w (A0)+,D0 ;GET FIRST word OF SRC BRA.S START ;AND GO TO LOOP START FILLOP MOVE.w -2(A0),D0 ;PUT SRCDATA IN DO 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 ? BNE.S DOCOPY ;NO, USE COPY LOOP CMP.w 2(A0),D0 ;THREE IN A ROW ? BNE.S DOCOPY ;NO, USE COPY LOOP BRA.S DOFILL ;YES, USE FILL LOOP NXTCOPY MOVE.w (A0)+,D0 ;GET word OF SRC CMP.w (A0),D0 ;IS THE NEXT THE SAME ? BNE.S DOCOPY ;NO, CONTINUE CMP.w 2(A0),D0 ;THREE IN A ROW ? BEQ.S COPYOP ;YES, END OF COPY RUN DOCOPY MOVE.w D0,(A1)+ ;COPY DATA TO DST DBRA D1,NXTCOPY ;AND LOOP FOR MORE ENDCOPY SUB A0,D2 ;COMPUTE COPYOP NEG D2 ;NEGATE ONLY asr.w #1,d2 ;make word count 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 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 NXTFILL CMP.w (A0)+,D0 ;IS NEXT word 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 #2,A0 ;BACK UP FOR LAST word COMPARED SUB A0,D2 ;COMPUTE FILLOP asr.w #1,d2 ;make word count 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 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 @4 MOVE.w D0,(A1)+ ;COPY IT TO DST 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