; ; File: Arith8Blt.a ; ; Contains: xxx put contents here (or delete the whole line) xxx ; ; Written by: xxx put name of writer here (or delete the whole line) xxx ; ; Copyright: © 1987-1990 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <5> 10/8/90 SMC Removed patchciRom tests in bTransparent8 and rTransparent8. ; They are now handled in QDciPatchROM.a. ; <4> 8/16/90 SMC Fixed horizontal pattern alignment of complex patterns in ; transparent and arithmetic slab transfer modes. ; <3> 1/29/90 BAL Fixed conditionals for JP build. ; <2> 1/28/90 KON Conditionalized an equate table for ci Rom patch. This file is ; included by QDciPatchROM.a. ; <1.1> 11/18/89 BAL Made a real part of 32-Bit QuickDraw 1.2 ; <1.0> 11/9/89 BAL Added to Ease ; <1.2> 1/16/89 CCH Merged 6.0.3 final sources into 7.0. ; <•1.1> 11/16/88 CCH Updated to newest version. ; 2/23/88 fixed arithmetic mode cache initialization (add and sub modes) (1.1) ; 2/22/88 fixed bug in 8-1 copybits (can't assume map is 0 or 1 only) ; 2/21/88 fixed wrong reg (A4 -> A2) bump bug in oval handler (MacDraw crash) ; (1.0) ; 2/21/88 fixed bug in arithmetic mode cache initialization ; 2/18/88 fixed bug in transparent mode fill (LSR instead of ASR) ; 2/18/88 fixed bug in unclipped, less than 5 wide arithmetic modes ; 2/7/88 added configuration code at startup time (.99) ; 2/4/88 fixed arithmetic mode bug with type 0 patterns (-$68, not -68!) (.987) ; AJH 05-Feb-88 converted to cdev ; 2/4/88 added transparent modes ; 2/2/88 added blend mode; fixed arithmetic copyBits bug AJH 03-Feb-88 removed ; hilite by invert hack (.985) AJH 03-Feb-88 further optimized ; hilite, 1 to 8 copybits ; 2/1/88 added arithmetic transfer mode fills for clipped rects (.98) ; 1/31/88 added arithmetic transfer mode fills for unclipped rects ; 1/30/88 added arithmetic transfer mode fills for rrects/ovals ; 1/29/88 added oval/rrects with complex patterns ; 1/28/88 check if already installed; if so, display logo AJH 29-Jan-88 removed ; OR mode complex fills; fixed OR mode simple fills AJH 29-Jan-88 ; reject patterns > 8 pixels wide ; 1/28/88 INIT wasn't locked bug (.97) ; 1/27/88 OR mode fills (simple and complex patterns) (.96) ; 1/26/88 added oval/rrects in OR mode ; 1/24/88 broke LogoPict into separate resource; separate 1-bit logo (.95) AJH ; 25-Jan-88 region counting for InvertClip AJH 26-Jan-88 ; significantly improved oval/rrects when unclipped ; 1/23/88 fixed bug when region is a mask (CB1to8 from CopyMask) ; 1/22/88 fixed OR mode fill, added $335 for MacDraw Plus ; 1/17/88 fixed scaling rejection bug in mapped copyBits AJH 18-Jan-88 ; implemented fast 8 to 1 copyBits; fixed 1-8 seekRgn bug (.94) ; AJH 20-Jan-88 region counting for clipped blit ; 1/16/88 fixed seek region bug in mapped copyBits (.93) ; 1/14/88 fixed bug in unclipped pattern fill (.92) ; 1/13/88 made fills work in modes other than 8-bit (.91) ; 1/11/88 st Beta release, version .9 ; ; To Do: ; ;EASE$$$ READ ONLY COPY of file “arith8blt.a” ; 1.1 BAL 11/18/1989 Made a real part of 32-Bit QuickDraw 1.2 ; 1.0 BAL 11/09/1989 Added to Ease ; END EASE MODIFICATION HISTORY ; 1.2 CCH 01/16/1989 Merged 6.0.3 final sources into 7.0. ;•1.1 CCH 11/16/1988 Updated to newest version. PRINT ON ; File QuickLoops.a ;----------------------------------------------------------------------------- ; ; High performance Mac II Color QuickDraw Inner Loops (for 8-bit mode) ; ; written by Andy Hertzfeld December 22, 1987 ; ; This INIT patches out some of the Color QuickDraw inner loop traps ; to improve 8-bit performance by a factor of 2 to 3 (or even more!) ; ; Modification History: ; ; AJH 11-Jan-88 1st Beta release, version .9 ; AJH 13-Jan-88 made fills work in modes other than 8-bit (.91) ; AJH 14-Jan-88 fixed bug in unclipped pattern fill (.92) ; AJH 16-Jan-88 fixed seek region bug in mapped copyBits (.93) ; AJH 17-Jan-88 fixed scaling rejection bug in mapped copyBits ; AJH 18-Jan-88 implemented fast 8 to 1 copyBits; fixed 1-8 seekRgn bug (.94) ; AJH 20-Jan-88 region counting for clipped blit ; AJH 22-Jan-88 fixed OR mode fill, added $335 for MacDraw Plus ; AJH 23-Jan-88 fixed bug when region is a mask (CB1to8 from CopyMask) ; AJH 24-Jan-88 broke LogoPict into separate resource; separate 1-bit logo (.95) ; AJH 25-Jan-88 region counting for InvertClip ; AJH 26-Jan-88 significantly improved oval/rrects when unclipped ; AJH 26-Jan-88 added oval/rrects in OR mode ; AJH 27-Jan-88 OR mode fills (simple and complex patterns) (.96) ; AJH 28-Jan-88 INIT wasn't locked bug (.97) ; AJH 28-Jan-88 check if already installed; if so, display logo ; AJH 29-Jan-88 removed OR mode complex fills; fixed OR mode simple fills ; AJH 29-Jan-88 reject patterns > 8 pixels wide ; AJH 29-Jan-88 added oval/rrects with complex patterns ; AJH 30-Jan-88 added arithmetic transfer mode fills for rrects/ovals ; AJH 31-Jan-88 added arithmetic transfer mode fills for unclipped rects ; AJH 01-Feb-88 added arithmetic transfer mode fills for clipped rects (.98) ; AJH 02-Feb-88 added blend mode; fixed arithmetic copyBits bug ; AJH 03-Feb-88 removed hilite by invert hack (.985) ; AJH 03-Feb-88 further optimized hilite, 1 to 8 copybits ; AJH 04-Feb-88 added transparent modes ; AJH 04-Feb-88 fixed arithmetic mode bug with type 0 patterns (-$68, not -68!) (.987) ; AJH 05-Feb-88 converted to cdev ; AJH 07-Feb-88 added configuration code at startup time (.99) ; AJH 18-Feb-88 fixed bug in transparent mode fill (LSR instead of ASR) ; AJH 18-Feb-88 fixed bug in unclipped, less than 5 wide arithmetic modes ; AJH 21-Feb-88 fixed bug in arithmetic mode cache initialization ; AJH 21-Feb-88 fixed wrong reg (A4 -> A2) bump bug in oval handler (MacDraw crash) (1.0) ; AJH 22-Feb-88 fixed bug in 8-1 copybits (can't assume map is 0 or 1 only) ; AJH 23-Feb-88 fixed arithmetic mode cache initialization (add and sub modes) (1.1) ; ;---- A New Life at Apple -------------------- ; ; PB415 DAF/BAL 01Mar88 QuickerDraw integrated into system patch files ; PB427 BAL 17Mar88 Corrected some edge masking bugs in arithmetic modes. ; Return to ROM if arithmetic mode copybits from left to right. ; PB428 DAF 18Mar88 Fixed QuickerDraw to be A/UX friendly. ; PB433 DAF 22Mar88 Improved dispatches to ROM (saved a couple of bytes and cycles) ; BAL 25Mar88 Converted to use symbolic stack frame references ; PB446 DBG 29Mar88 Fixed up missed JMPs into ROM in QuickerDraw.a, which cause certain ; CopyBits cases to crash. ; PB448 DBG 30Mar88 Fixed erroneous references to HBUMP to be to SRCBUMP ; PB452 BAL 01Apr88 Fixed bug in DrawSlab OR mode handler ($381) to preserve fgColor ; PB471 BAL 18Apr88 Fixed 1 to 8 bit expansion to first insure CLUT is B/W. ; PB473 DAF 19Apr88 Modified PB471 to allow more cases to be accelerated. ; PB471 BAL/DVB 13Jun88 Fixed 1 to 8 bit expansion to first insure src = scalebuf ; (i.e. dest not before pixmap's baseAddr). ; PBnnn d√b 12Jul88 Fixed error in 8 to 1 when white doesn't map to white. ; ;-------------------------------------------------------------------------------------------------- fooo proc ; make following defines global endproc IF (&TYPE('patchciRom') = 'UNDEFINED') THEN patchciRom EQU 0 ENDIF MACHINE MC68020 ; for reference, here are the patched traps IF 0 THEN InstToolTp AddOverFillO,$38A InstToolTp SubOverFillO,$38E InstToolTp AddPinFillO,$389 InstToolTp SubPinFillO,$38B InstToolTp AddMaxFillO,$38D InstToolTp AddMinFillO,$38F InstToolTp BlendFillO,$388 InstToolTp TransFillO,$38C InstToolTp AddOverFillR,$368 InstToolTp SubOverFillR,$36C InstToolTp AddPinFillR,$367 InstToolTp SubPinFillR,$369 InstToolTp AddMaxFillR,$36B InstToolTp AddMinFillR,$36D InstToolTp BlendFillR,$366 InstToolTp TransFillR,$36A InstToolTp AddOverUnClip,$352 InstToolTp SubOverUnClip,$356 InstToolTp AddPinUnClip,$351 InstToolTp SubPinUnClip,$353 InstToolTp AddMaxUnClip,$355 InstToolTp AddMinUnClip,$357 InstToolTp BlendUnClip,$350 InstToolTp TransUnClip,$354 ENDIF ;****************************************************************************************** ; ; to make scoping for upcoming equates happier, we force the end of the previous procedure here ; QuickerDraw PROC EXPORT EXPORT slAddOver8 EXPORT slSubOver8 EXPORT slAddPin8 EXPORT slSubPin8 EXPORT slMax8 EXPORT slMin8 EXPORT slAvg8 EXPORT rAddOver8 EXPORT rSubOver8 EXPORT rAddPin8 EXPORT rSubPin8 EXPORT rMax8 EXPORT rMin8 EXPORT rAvg8 EXPORT bAddOver8 EXPORT bSubOver8 EXPORT bAddPin8 EXPORT bSubPin8 EXPORT bMax8 EXPORT bMin8 EXPORT bAvg8 EXPORT slTransparent8 EXPORT rTransparent8 EXPORT bTransparent8 if patchciRom THEN ; now patch the inner loop traps; so far we handle: Old350 EQU $2DAD0 ; bAvg-- blend fill, unclipped rects Old351 EQU $2D450 ; bAddPin-- addPin fill, unclipped rects Old352 EQU $2D340 ; bAddOver-- addOver fill, unclipped rects (and bitmaps) Old353 EQU $2D6E0 ; bSubPin-- subPin fill, unclipped rects Old354 EQU $2DE80 ; bTransparent-- transparent fill, unclipped rects Old355 EQU $2D870 ; bMax-- addMax fill, unclipped rects Old356 EQU $2D5D0 ; bSubOver-- subOver fill, unclipped rects Old357 EQU $2D9A0 ; bMin-- addMin fill, unclipped rects Old366 EQU $2BBB0 ; rAvg-- blend fill, clipped rects Old367 EQU $2B4C0 ; rAddPin-- addPin fill, clipped rects Old368 EQU $2B3A0 ; rAddOver-- addOver fill, clipped rects (and bitmaps) Old369 EQU $2B790 ; rSubPin-- subPin fill, clipped rects Old36A EQU $2C060 ; rTransparent-- transparent fill, clipped rects Old36B EQU $2B930 ; rMax-- addMax fill, clipped rects Old36C EQU $2B660 ; rSubOver-- subOver fill, clipped rects Old36D EQU $2BA70 ; rMin-- addMin fill, clipped rects Old388 EQU $2F670 ; slAvg-- blend fill, ovals Old389 EQU $2F3E0 ; slAddPin-- addPin fill, ovals Old38A EQU $2F330 ; slAddOver-- addOver fill, ovals Old38B EQU $2F4E0 ; slSubPin-- subPin fill, ovals Old38C EQU $2F790 ; slTransparent-- transparent fill, ovals Old38D EQU $2F570 ; slMax-- AddMax fill, ovals Old38E EQU $2F470 ; slSubOver-- subOver fill, ovals Old38F EQU $2F5F0 ; slMin-- AddMin fill, ovals Old380 EQU $2F1C4 ; slMASK8-- oval/rrect copy mode scan line handler Old381 EQU $2F1E6 ; slMASK9-- oval/rrect OR mode scan line handler Old384 EQU $2F230 ; slXMask8-- oval/rrect complex fill, copy mode ELSEIF 0 THEN ;these are the equates for MacII Old350 EQU $1BF24 ; bAvg-- blend fill, unclipped rects Old351 EQU $1BC6A ; bAddPin-- addPin fill, unclipped rects Old352 EQU $1BBF4 ; bAddOver-- addOver fill, unclipped rects (and bitmaps) Old353 EQU $1BD7C ; bSubPin-- subPin fill, unclipped rects Old354 EQU $1C0B0 ; bTransparent-- transparent fill, unclipped rects Old355 EQU $1BE18 ; bMax-- addMax fill, unclipped rects Old356 EQU $1BD06 ; bSubOver-- subOver fill, unclipped rects Old357 EQU $1BE9E ; bMin-- addMin fill, unclipped rects Old366 EQU $1CF94 ; rAvg-- blend fill, clipped rects Old367 EQU $1CDE8 ; rAddPin-- addPin fill, clipped rects Old368 EQU $1CD9C ; rAddOver-- addOver fill, clipped rects (and bitmaps) Old369 EQU $1CE88 ; rSubPin-- subPin fill, clipped rects Old36A EQU $1D094 ; rTransparent-- transparent fill, clipped rects Old36B EQU $1CEDC ; rMax-- addMax fill, clipped rects Old36C EQU $1CE3C ; rSubOver-- subOver fill, clipped rects Old36D EQU $1CF38 ; rMin-- addMin fill, clipped rects Old388 EQU $1E1BE ; slAvg-- blend fill, ovals Old389 EQU $1DF50 ; slAddPin-- addPin fill, ovals Old38A EQU $1DEBA ; slAddOver-- addOver fill, ovals Old38B EQU $1E042 ; slSubPin-- subPin fill, ovals Old38C EQU $1E2CE ; slTransparent-- transparent fill, ovals Old38D EQU $1E0CE ; slMax-- AddMax fill, ovals Old38E EQU $1DFDA ; slSubOver-- subOver fill, ovals Old38F EQU $1E146 ; slMin-- AddMin fill, ovals Old380 EQU $1DD7E ; slMASK8-- oval/rrect copy mode scan line handler Old381 EQU $1DD9A ; slMASK9-- oval/rrect OR mode scan line handler Old384 EQU $1DDCE ; slXMask8-- oval/rrect complex fill, copy mode ENDIF ;---------------------------------------------------- ; ; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK: ; ; STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS. ; &CurFile SETC 'STRETCH' INCLUDE 'DrawingVars.a' ;****************************************************************************************** ; Arithmetic transfer modes start here... ;****************************************************************************************** ; Here's where we implement the arithmetic transfer mode fills for ovals/rrects ; Use a common loop for all the transfer modes, with specialized handlers to do the ; pixel arithmetic. ; the first receiver is for AddOver mode for ovals and roundRects ;>>>>>>>>>>> AddOverFillO slAddOver8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old38A ; continue in ROM endif ; OK, first do the pattern setup @0 MOVE.L A0,A3 ;set up pattern base LEA AddOverHandler,A0 ;use addOver DoArithMode MOVEM.L D7/A4-A5,-(SP) ;save work regs BSR.S ArithModeHandler ;invoke the handler MOVEM.L (SP)+,D7/A4-A5 ;restore regs RTS ; here is the general handler for a scan line of arithmetic fills ArithModeHandler MOVEQ #0,D6 ;init pattern index MOVE.W PATROW(A6),D4 ;get pattern size in bytes SUBQ #4,D4 ;is it a simple one? BLE ArithSimplePat ;if so, handle faster ; sometimes simple patterns come in as 8 byte ones, so check for that MOVE.W PATHPOS(A6),D6 ; ASR.W #3,D6 ;turn bits back into bytes ADD.W D0,D6 ; SUBQ #4,D4 ;is it 8 long? BNE.S ArithComplexPat ;if not, skip ; fetch both halves of the pattern and see if they match MOVE.W PATHMASK(A6),D4 ;get pattern mask ASR #3,D4 ;turn bit index to byte index AND.W D4,D6 ;mask it MOVE.L EXPAT(A6),A4 ADD.l PATVPOS(A6),A4 ;compute pattern address MOVE.L 0(A4,D6),D4 ;get source longword EOR #4,D6 CMP.L 0(A4,D6),D4 ;is it really simple? BEQ ArithSimplePat ;if so, go handle EOR #4,D6 ;restore D6 ; set up the pattern variables, since it's a complex pattern ArithComplexPat MOVE.L EXPAT(A6),A3 ADD.l PATVPOS(A6),A3 ;compute pattern address ArithComplex1 MOVE.L D1,-(SP) ;remember right edge mask MOVEQ #0,D1 MOVEQ #0,D7 ;clear for pixCache ; set up A0 to point to the proper handler, depending on the width of the inverse table MOVE.L A0,A4 ;remember handler base MOVE.W INVSIZE(A6),D4 ;get shift count (3,4,5) SUBQ #3,D4 ADD.W 0(A0,D4.W*2),A0 ;point to proper handler ; init the single pixel cache, where D1 is last source, D7 is last dest, and D0 is last result MOVEQ #0,D5 MOVE.L COLORTABLE(A6),A5 ;get color table ptr MOVE.B D1,D5 LEA 0(A5,D5.W*8),A4 ;point to source color MOVE.B D7,D5 LEA 0(A5,D5.W*8),A5 ;point to dest color JSR (A0) ;map it MOVE.B ([INVCOLOR,A6],D0.W,6),D0 ;look up in inverse table ; test for the single long case TST.W D2 BRA ArithBot0 ; here's the main loop for complex patterns, where we process a longword at a time ; use a single pixel cache for speed using D0, D1 and D7 ArithRight0 AND.L (SP)+,D3 ArithLoop0 MOVE.W PATHMASK(A6),D4 ;get pattern mask ASR #3,D4 ;turn bit index to byte index AND.W D4,D6 ;mask it MOVE.L 0(A3,D6),D4 ;get source longword ADDQ #4,D6 MOVE.L A2,D5 ;no clipping? BEQ.S @0 ;if none, skip AND.L (A2)+,D3 ;get region/edge mask in D3 BEQ ArithMask0 @0 MOVE.L (A1),D5 ;get dest longword ; map 1st byte TST.B D3 BEQ.S @8 ;if mask zero, we can skip ; if same as previous, we can short-circuit the mapping CMP.B D4,D1 ;source the same? BNE.S @9 ;if not, skip CMP.B D5,D7 ;dest the same? BNE.S @9 ;if not, skip ; it's the same, so use it MOVE.B D0,D5 ;use last result BRA.S @8 ;skip the mapping ; it's different than the last one, so map it @9 MOVE.B D4,D1 MOVE.L COLORTABLE(A6),A5 LEA 0(A5,D1.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A5,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table MOVE.B D5,D0 @8 LSR.L #8,D3 LSR.L #8,D4 ROR.L #8,D5 ; map 2nd byte TST.B D3 BEQ.S @2 ;if mask zero, we can skip ; if same as previous, we can short-circuit the mapping CMP.B D4,D1 ;source the same? BNE.S @1 ;if not, skip CMP.B D5,D7 ;dest the same? BNE.S @1 ;if not, skip ; it's the same, so use it MOVE.B D0,D5 ;use last result BRA.S @2 ;skip the mapping ; it's different than the last one, so map it @1 MOVE.B D4,D1 MOVE.L COLORTABLE(A6),A5 LEA 0(A5,D1.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A5,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table MOVE.B D5,D0 @2 LSR.L #8,D3 LSR.L #8,D4 ROR.L #8,D5 ; map 3rd byte TST.B D3 BEQ.S @4 ;if mask zero, we can skip ; if same as previous, we can short-circuit the mapping CMP.B D4,D1 ;source the same? BNE.S @3 ;if not, skip CMP.B D5,D7 ;dest the same? BNE.S @3 ;if not, skip ; it's the same, so use it MOVE.B D0,D5 ;use last result BRA.S @4 ;skip the mapping ; it's different than the last one, so map it @3 MOVE.B D4,D1 MOVE.L COLORTABLE(A6),A5 LEA 0(A5,D1.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A5,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table MOVE.B D5,D0 @4 LSR.L #8,D3 LSR.L #8,D4 ROR.L #8,D5 ; map final byte TST.B D3 BEQ.S @6 ;if mask zero, we can skip ; if same as previous, we can short-circuit the mapping CMP.B D4,D1 ;source the same? BNE.S @5 ;if not, skip CMP.B D5,D7 ;dest the same? BNE.S @5 ;if not, skip ; it's the same, so use it MOVE.B D0,D5 ;use last result BRA.S @6 ;skip the mapping ; it's different than the last one, so map it @5 MOVE.B D4,D1 MOVE.L COLORTABLE(A6),A5 LEA 0(A5,D1.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A5,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table MOVE.B D5,D0 @6 ROR.L #8,D5 ; it's all mapped, so store the result MOVE.L D5,(A1)+ ;store the destination ArithBotCommon MOVEQ #-1,D3 ;set up the mask for the middle SUBQ #1,D2 ArithBot0 BGT ArithLoop0 BEQ ArithRight0 ; all done with this scan line RTS ; handle a region of all zeros ArithMask0 ADDQ #4,A1 ;skip over destination BRA.S ArithBotCommon ; the pattern is simpler (it fits in a register), so use a separate loop to make things ;faster. Use a longword cache instead of the single pixel caches. ArithSimplePat MOVE.L D1,-(SP) ;save right edge mask MOVEQ #0,D7 ;clear for pixIndexing MOVE.L (A3),D4 ;keep pattern in D4 MOVE.L COLORTABLE(A6),A3 ;use A3 for color table ptr ; set up A0 to point to the proper handler, depending on the width of the inverse table MOVE.L A0,A4 ;remember handler base MOVE.W INVSIZE(A6),D0 ;get shift count (3,4,5) SUBQ #3,D0 ADD.W 0(A0,D0.W*2),A0 ;point to proper handler ; init the longword pattern cache by mapping the four pixels in D4 MOVEQ #3,D5 MOVE.L D4,D6 ;init lastDest BRA.S CacheILoop0 ;skip cache check 1st time ; if the next pixel in D4 is the same as the previous (in D7), take a shortcut CacheInitLoop CMP.B D4,D7 ;does it match? BNE.S CacheILoop0 ;if not, must do the hard way MOVE.B D0,D1 ;use last result ROL.L #8,D1 ROL.L #8,D4 DBRA D5,CacheInitLoop BRA.S CacheIDone ; it's not the same, so do it the hard way CacheILoop0 MOVE.B D4,D7 LEA 0(A3,D7.W*8),A4 ;point to source color MOVE.L A4,A5 ;source and dest are same JSR (A0) ;map next pixel MOVE.B ([INVCOLOR,A6],D0.W,6),D1 ;look up in inverse table MOVE.L D1,D0 ;remember last result ROL.L #8,D1 ROL.L #8,D4 DBRA D5,CacheInitLoop ; OK, here's the start of the main loop; first, see if there's only one long to do CacheIDone TST.W D2 BNE.S ArithLoop1 ; here's the main loop for simple patterns, where we process a longword at a time ; We use a longword cache in D6 ArithRight1 AND.L (SP)+,D3 ArithLoop1 MOVE.L A2,D5 ;no clipping? BEQ.S @0 ;if none, skip AND.L (A2)+,D3 ;get mask in D4 BEQ ArithMask1 @0 MOVE.L (A1),D5 ;get dest longword CMP.L #-1,D3 ;mask all ones? BNE.S ArithMapIt1A ;if not, can't use cache CMP.L D5,D6 ;same as last time? BNE.S ArithMapIt1 ;if not, skip ; the long was the same as last time, so we can skip the mapping. Better make sure ; the mask was the same, too MOVE.L D1,D5 ;use last result BRA ArithStoreIt ;skip the mapping ; it was different, so we have to map it the hard way ArithMapIt1 MOVE.L D5,D6 ;remember for next time ArithMapIt1A TST.B D3 BEQ.S @0 ;if mask zero, we can skip MOVE.B D4,D7 LEA 0(A3,D7.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A3,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table @0 ROR.L #8,D3 ROR.L #8,D4 ROR.L #8,D5 ; map 2nd byte TST.B D3 BEQ.S @2 ;if mask zero, we can skip MOVE.B D4,D7 LEA 0(A3,D7.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A3,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table @2 ROR.L #8,D3 ROR.L #8,D4 ROR.L #8,D5 ; map 3rd byte TST.B D3 BEQ.S @4 ;if mask zero, we can skip ; map it MOVE.B D4,D7 LEA 0(A3,D7.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A3,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table @4 ROR.L #8,D3 ROR.L #8,D4 ROR.L #8,D5 ; map final byte TST.B D3 BEQ.S @6 ;if mask zero, we can skip ; it's different than the last one, so map it MOVE.B D4,D7 LEA 0(A3,D7.W*8),A4 ;point to source color MOVE.B D5,D7 LEA 0(A3,D7.W*8),A5 ;point to dest color JSR (A0) ;map according to Xfer mode MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table @6 ROR.L #8,D4 ROR.L #8,D5 ; it's all mapped, so store the result ArithStoreIt MOVE.L D5,(A1)+ ;store the destination ADDQ.L #1,D3 ;was mask all ones? BNE.S ArithCom1 ;if not, skip MOVE.L D5,D1 ;remember last result ArithCom1 MOVEQ #-1,D3 ;set up the mask for the middle SUBQ #1,D2 ArithBot1 BGT ArithLoop1 BEQ ArithRight1 ; all done with this scan line RTS ; handle a region of all zeros ArithMask1 ADDQ #4,A1 ;skip over destination BRA.S ArithCom1 ; Here is the handler for the AddOver mode. A4 points to the source RGBColor, while ; A5 points to the destination. Return the index in D0 (to be looked up in the ; inverse table). First there is a case table for using a static shift count AddOverHandler DC.W AddOver3-AddOverHandler DC.W AddOver4-AddOverHandler DC.W AddOver5-AddOverHandler AddOver3 MOVEQ #0,D0 MOVE.W (A4)+,D0 ;red ADD.W (A5)+,D0 LSL.L #3,D0 MOVE.W (A4)+,D0 ;green ADD.W (A5)+,D0 LSL.L #3,D0 MOVE.W (A4),D0 ;blue ADD.W (A5),D0 LSL.L #3,D0 SWAP D0 ;return inverse table index RTS AddOver4 MOVEQ #0,D0 MOVE.W (A4)+,D0 ;red ADD.W (A5)+,D0 LSL.L #4,D0 MOVE.W (A4)+,D0 ;green ADD.W (A5)+,D0 LSL.L #4,D0 MOVE.W (A4),D0 ;blue ADD.W (A5),D0 LSL.L #4,D0 SWAP D0 ;return inverse table index RTS AddOver5 MOVEQ #0,D0 MOVE.W (A4)+,D0 ;red ADD.W (A5)+,D0 LSL.L #5,D0 MOVE.W (A4)+,D0 ;green ADD.W (A5)+,D0 LSL.L #5,D0 MOVE.W (A4),D0 ;blue ADD.W (A5),D0 LSL.L #5,D0 SWAP D0 ;return inverse table index RTS ;************************************************************************************* ; Here is the receiver for the SubOver arithmetic fill mode, for ovals and roundRects. ; It uses mainly common code with the other oval handlers ;>>>>>>>>>>> SubOverFillO slSubOver8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old38E ; endif ; OK, first do the pattern setup @0 MOVE.L A0,A3 ;set up pattern base LEA SubOverHandler,A0 ;use subOver BRA DoArithMode ; Here is the handler for the SubOver mode. A4 points to the source RGBColor, while ; A5 points to the destination. Return the index in D0 (to be looked up in the ; inverse table). First there is a case table for using a static shift count SubOverHandler DC.W SubOver3-SubOverHandler DC.W SubOver4-SubOverHandler DC.W SubOver5-SubOverHandler SubOver3 MOVEQ #0,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #3,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #3,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #3,D0 SWAP D0 ;return inverse table index RTS SubOver4 MOVEQ #0,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #4,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #4,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #4,D0 SWAP D0 ;return inverse table index RTS SubOver5 MOVEQ #0,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #5,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #5,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 LSL.L #5,D0 SWAP D0 ;return inverse table index RTS ;************************************************************************************* ; Here is the receiver for the AddPin arithmetic fill mode, for ovals and roundRects. ; It uses mainly common code with the other oval handlers ;>>>>>>>>>>> AddPinFillO slAddPin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old389 ; endif ; set up handlers and use common code @0 MOVE.L A0,A3 ;set up pattern base LEA AddPinHandler,A0 ;use addPin BRA DoArithMode ; Here is the handler for the AddPin mode. A4 points to the source RGBColor, while ; A5 points to the destination. Return the index in D0 (to be looked up in the ; inverse table). First there is a case table for using a static shift count AddPinHandler DC.W AddPin3-AddPinHandler DC.W AddPin4-AddPinHandler DC.W AddPin5-AddPinHandler AddPin3 MOVEQ #0,D0 MOVE.W (A4)+,D0 ;red ADD.W (A5)+,D0 BCS.S @0 CMP.W WEIGHT+BLUE(A6),D0 BLS.S @1 @0 MOVE.W WEIGHT+BLUE(A6),D0 @1 LSL.L #3,D0 MOVE.W (A4)+,D0 ;green ADD.W (A5)+,D0 BCS.S @2 CMP.W WEIGHT+GREEN(A6),D0 BLS.S @3 @2 MOVE.W WEIGHT+GREEN(A6),D0 @3 LSL.L #3,D0 MOVE.W (A4),D0 ;blue ADD.W (A5),D0 BCS.S @4 CMP.W WEIGHT+RED(A6),D0 BLS.S @5 @4 MOVE.W WEIGHT+RED(A6),D0 @5 LSL.L #3,D0 SWAP D0 ;return inverse table index RTS AddPin4 MOVEQ #0,D0 MOVE.W (A4)+,D0 ;red ADD.W (A5)+,D0 BCS.S @0 CMP.W WEIGHT+BLUE(A6),D0 BLS.S @1 @0 MOVE.W WEIGHT+BLUE(A6),D0 @1 LSL.L #4,D0 MOVE.W (A4)+,D0 ;green ADD.W (A5)+,D0 BCS.S @2 CMP.W WEIGHT+GREEN(A6),D0 BLS.S @3 @2 MOVE.W WEIGHT+GREEN(A6),D0 @3 LSL.L #4,D0 MOVE.W (A4),D0 ;blue ADD.W (A5),D0 BCS.S @4 CMP.W WEIGHT+RED(A6),D0 BLS.S @5 @4 MOVE.W WEIGHT+RED(A6),D0 @5 LSL.L #4,D0 SWAP D0 ;return inverse table index RTS AddPin5 MOVEQ #0,D0 MOVE.W (A4)+,D0 ;red ADD.W (A5)+,D0 BCS.S @0 CMP.W WEIGHT+BLUE(A6),D0 BLS.S @1 @0 MOVE.W WEIGHT+BLUE(A6),D0 @1 LSL.L #5,D0 MOVE.W (A4)+,D0 ;green ADD.W (A5)+,D0 BCS.S @2 CMP.W WEIGHT+GREEN(A6),D0 BLS.S @3 @2 MOVE.W WEIGHT+GREEN(A6),D0 @3 LSL.L #5,D0 MOVE.W (A4),D0 ;blue ADD.W (A5),D0 BCS.S @4 CMP.W WEIGHT+RED(A6),D0 BLS.S @5 @4 MOVE.W WEIGHT+RED(A6),D0 @5 LSL.L #5,D0 SWAP D0 ;return inverse table index RTS ;************************************************************************************* ; Here is the receiver for the SubPin arithmetic fill mode, for ovals and roundRects. ; It uses mainly common code with the other oval handlers ;>>>>>>>>>>> SubPinFillO slSubPin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old38B ; endif ; set up handlers and use common code @0 MOVE.L A0,A3 ;set up pattern base LEA SubPinHandler,A0 ;use SubPin BRA DoArithMode ; Here is the handler for the SubPin mode. A4 points to the source RGBColor, while ; A5 points to the destination. Return the index in D0 (to be looked up in the ; inverse table). First there is a case table for using a static shift count SubPinHandler DC.W SubPin3-SubPinHandler DC.W SubPin4-SubPinHandler DC.W SubPin5-SubPinHandler SubPin3 MOVEQ #0,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @0 CMP.W WEIGHT+BLUE(A6),D0 BCC.S @1 @0 MOVE.W WEIGHT+BLUE(A6),D0 @1 LSL.L #3,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @2 CMP.W WEIGHT+GREEN(A6),D0 BCC.S @3 @2 MOVE.W WEIGHT+GREEN(A6),D0 @3 LSL.L #3,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @4 CMP.W WEIGHT+RED(A6),D0 BCC.S @5 @4 MOVE.W WEIGHT+RED(A6),D0 @5 LSL.L #3,D0 SWAP D0 ;return inverse table index RTS SubPin4 MOVEQ #0,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @0 CMP.W WEIGHT+BLUE(A6),D0 BCC.S @1 @0 MOVE.W WEIGHT+BLUE(A6),D0 @1 LSL.L #4,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @2 CMP.W WEIGHT+GREEN(A6),D0 BCC.S @3 @2 MOVE.W WEIGHT+GREEN(A6),D0 @3 LSL.L #4,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @4 CMP.W WEIGHT+RED(A6),D0 BCC.S @5 @4 MOVE.W WEIGHT+RED(A6),D0 @5 LSL.L #4,D0 SWAP D0 ;return inverse table index RTS SubPin5 MOVEQ #0,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @0 CMP.W WEIGHT+BLUE(A6),D0 BCC.S @1 @0 MOVE.W WEIGHT+BLUE(A6),D0 @1 LSL.L #5,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @2 CMP.W WEIGHT+GREEN(A6),D0 BCC.S @3 @2 MOVE.W WEIGHT+GREEN(A6),D0 @3 LSL.L #5,D0 MOVE.W (A5)+,D0 ;red SUB.W (A4)+,D0 BCS.S @4 CMP.W WEIGHT+RED(A6),D0 BCC.S @5 @4 MOVE.W WEIGHT+RED(A6),D0 @5 LSL.L #5,D0 SWAP D0 ;return inverse table index RTS ;************************************************************************************* ; Here is the receiver for the AddMax arithmetic fill mode, for ovals and roundRects. ; It uses mainly common code with the other oval handlers ;>>>>>>>>>>> AddMaxFillO slMax8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old38D ; endif ; OK, first do the pattern setup @0 MOVE.L A0,A3 ;set up pattern base LEA AddMaxHandler,A0 ;use AddMax BRA DoArithMode ; Here is the handler for the AddMax mode. A4 points to the source RGBColor, while ; A5 points to the destination. Return the index in D0 (to be looked up in the ; inverse table). First there is a case table for using a static shift count AddMaxHandler DC.W AddMax3-AddMaxHandler DC.W AddMax4-AddMaxHandler DC.W AddMax5-AddMaxHandler AddMax3 MOVEQ #0,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @0 MOVE.W (A5),D0 @0 ADDQ #2,A5 LSL.L #3,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @1 MOVE.W (A5),D0 @1 ADDQ #2,A5 LSL.L #3,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @2 MOVE.W (A5),D0 @2 ADDQ #2,A5 LSL.L #3,D0 SWAP D0 ;return inverse table index RTS AddMax4 MOVEQ #0,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @0 MOVE.W (A5),D0 @0 ADDQ #2,A5 LSL.L #4,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @1 MOVE.W (A5),D0 @1 ADDQ #2,A5 LSL.L #4,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @2 MOVE.W (A5),D0 @2 ADDQ #2,A5 LSL.L #4,D0 SWAP D0 ;return inverse table index RTS AddMax5 MOVEQ #0,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @0 MOVE.W (A5),D0 @0 ADDQ #2,A5 LSL.L #5,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @1 MOVE.W (A5),D0 @1 ADDQ #2,A5 LSL.L #5,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BCC.S @2 MOVE.W (A5),D0 @2 ADDQ #2,A5 LSL.L #5,D0 SWAP D0 ;return inverse table index RTS ;************************************************************************************* ; Here is the receiver for the AddMin arithmetic fill mode, for ovals and roundRects. ; It uses mainly common code with the other oval handlers ;>>>>>>>>>>> AddMinFillO slMin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old38F ; endif ; OK, first do the pattern setup @0 MOVE.L A0,A3 ;set up pattern base LEA AddMinHandler,A0 ;use addMin BRA DoArithMode ; Here is the handler for the AddMin mode. A4 points to the source RGBColor, while ; A5 points to the destination. Return the index in D0 (to be looked up in the ; inverse table). First there is a case table for using a static shift count AddMinHandler DC.W AddMin3-AddMinHandler DC.W AddMin4-AddMinHandler DC.W AddMin5-AddMinHandler AddMin3 MOVEQ #0,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @0 MOVE.W (A5),D0 @0 ADDQ #2,A5 LSL.L #3,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @1 MOVE.W (A5),D0 @1 ADDQ #2,A5 LSL.L #3,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @2 MOVE.W (A5),D0 @2 ADDQ #2,A5 LSL.L #3,D0 SWAP D0 ;return inverse table index RTS AddMin4 MOVEQ #0,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @0 MOVE.W (A5),D0 @0 ADDQ #2,A5 LSL.L #4,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @1 MOVE.W (A5),D0 @1 ADDQ #2,A5 LSL.L #4,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @2 MOVE.W (A5),D0 @2 ADDQ #2,A5 LSL.L #4,D0 SWAP D0 ;return inverse table index RTS AddMin5 MOVEQ #0,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @0 MOVE.W (A5),D0 @0 ADDQ #2,A5 LSL.L #5,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @1 MOVE.W (A5),D0 @1 ADDQ #2,A5 LSL.L #5,D0 MOVE.W (A4)+,D0 CMP.W (A5),D0 BLS.S @2 MOVE.W (A5),D0 @2 ADDQ #2,A5 LSL.L #5,D0 SWAP D0 ;return inverse table index RTS ;************************************************************************************* ; Here is the receiver for the blend arithmetic fill mode, for ovals and roundRects. ; It uses mainly common code with the other oval handlers ;>>>>>>>>>>> BlendFillO slAvg8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old388 ; endif ; OK, first do the pattern setup @0 MOVE.L A0,A3 ;set up pattern base LEA BlendHandler,A0 ;use blend BRA DoArithMode ; Here is the handler for the Blend mode. A4 points to the source RGBColor, while ; A5 points to the destination. Return the index in D0 (to be looked up in the ; inverse table). First there is a case table for using a static shift count BlendHandler DC.W Blend3-BlendHandler DC.W Blend4-BlendHandler DC.W Blend5-BlendHandler Blend3 MOVEM.L D1-D3,-(SP) MOVEQ #3,D2 ;set up shift count BRA.S BlendCommon Blend4 MOVEM.L D1-D3,-(SP) MOVEQ #4,D2 BlendCommon MOVEQ #0,D0 ;clear accum reg ; do red MOVE.W (A4)+,D1 MULU WEIGHT+BLUE(A6),D1 MOVE.W (A5)+,D3 MULU NOTWEIGHT+BLUE(A6),D3 ADD.L D1,D3 SWAP D3 MOVE.W D3,D0 ASL.L D2,D0 ; do green MOVE.W (A4)+,D1 MULU WEIGHT+GREEN(A6),D1 MOVE.W (A5)+,D3 MULU NOTWEIGHT+GREEN(A6),D3 ADD.L D1,D3 SWAP D3 MOVE.W D3,D0 ASL.L D2,D0 ; do blue MOVE.W (A4)+,D1 MULU WEIGHT+RED(A6),D1 MOVE.W (A5)+,D3 MULU NOTWEIGHT+RED(A6),D3 ADD.L D1,D3 SWAP D3 MOVE.W D3,D0 ASL.L D2,D0 SWAP D0 MOVEM.L (SP)+,D1-D3 RTS Blend5 MOVEM.L D1-D3,-(SP) MOVEQ #5,D2 BRA.S BlendCommon ;****************************************************************************************** ; Now we start on the arithmetic fills for clipped rectangles. Use the common ; scan line handler for ovals/rrects to save code. ; First we handle AddOver mode if patchciRom THEN UseOld368 JMPROM Old368 ; endif ;>>>>>>>>>>> AddOverFillR rAddOver8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld368 ;if not, skip tst.l d3 ;right to left? bmi.s UseOld368 ;if so, skip endif LEA AddOverHandler,A0 ;set up the handler ArithFillCommon MOVE.L A0,-(SP) ;remember handler address ; set up the registers and invoke the common scan-line handler MOVE.L A4,A2 ;set up region pointer ASR #3,D6 ;bit index to byte index MOVE.L A5,A1 ;set up destination ArithFillLoop MOVEQ #-1,D1 MOVEQ #-1,D3 ;edge masks all ones (edges in region) MOVE.W BUFSIZE(A6),D2 ;set up the count ADDQ #4,D2 ;make one based LSR.W #2,D2 SUBQ #1,D2 ;make zero based MOVE.L (SP),A0 ;get handler address ; call the appropriate handle, depending on whether the pattern is simple or complex CMP.W #8,PATROW(A6) ;is pattern real complex? BGT.S @0 ;if so, go handle it TST.B endSwitch(A6) ;test pattern mode BMI.S @0 ;treat bitmap as complex MOVE.L 0(A3,D6),D0 ;get left pattern EOR #4,D6 CMP.L 0(A3,D6),D0 ;left same as right? BEQ.S @1 ;if so, it's simple EOR #4,D6 ;restore D6 @0 BSR ArithComplex1 ;invoke scan-line handler for complex pats BRA.S @2 @1 EOR #4,D6 BSR ArithSimplePat ; bump pointers to next time, and loop until done @2 MOVE.L patOffset(A6),D6 ;get pattern index ASR.L #3,D6 ;bit index to byte index moveq #0,d0 ;patPos should be a long MOVE.W patPos(A6),D0 TST.B endSwitch(A6) ;test pattern mode BEQ.S AFPat1 ;if zero, handle BMI.S AFBitMap1 ;if <0, go handle bitmap ; handle bumping the pattern pointers MOVE.L SRCADDR(A6),A3 ;set up pattern pointer SUB.l D0,A3 ADD.W PATROW(A6),D0 AND.W PATVMASK(A6),D0 MOVE.W D0,patPos(A6) ADD.l D0,A3 BRA.S AFSetPatPtr ; handle second type of pattern AFPat1 ADDQ #1,D0 AND #15,D0 LEA ([EXPAT,A6],D0.W*4),A3 MOVE.W D0,patPos(A6) AFSetPatPtr MOVE.L A3,SRCADDR(A6) ; bump to the next scan line ArithFillNextLine MOVE.L DSTROW(A6),D0 ADD.L D0,DSTADDR(A6) MOVE.W VERT(A6),D0 ADD.W VBUMP(A6),D0 MOVE.W D0,VERT(A6) CMP.W LASTV(A6),D0 BNE.S @0 ; all done, so strip stack and return MOVE.L SAVESTK2(A6),A7 RTS ; set up registers and loop for the next line @0 MOVE.L SEEKMASK(A6),A0 JSR (A0) ;seek new region MOVE.L SRCADDR(A6),A3 ;set up pattern pointer MOVE.L DSTADDR(A6),A1 ;set up dest ptr MOVE.L RGNADDR(A6),A2 ;set up region ptr BRA ArithFillLoop ; handle bumping the source if it's a bitmap AFBitMap1 MOVE.L SRCROW(A6),D0 ADD.L D0,SRCADDR(A6) BRA.S ArithFillNextLine ;****************************************************************************************** ; Handle SubOver clipped rectangle fill if patchciRom THEN UseOld36C JMPRom Old36C ; endif ;>>>>>>>>>>> SubOverFillR rSubOver8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld36C ;if not, skip tst.l d3 ;right to left? bmi.s UseOld36c ;if so, skip endif LEA SubOverHandler,A0 ;set up the handler BRA ArithFillCommon ;use comon code ;****************************************************************************************** ; Handle AddPin clipped rectangle fill if patchciRom THEN UseOld367 JMPRom Old367 ; endif ;>>>>>>>>>>> AddPinFillR rAddPin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld367 ;if not, skip tst.l d3 ;right to left? bmi.s UseOld367 ;if so, skip endif LEA AddPinHandler,A0 ;set up the handler BRA ArithFillCommon ;use comon code ;****************************************************************************************** ; Handle SubPin clipped rectangle fill if patchciRom THEN UseOld369 JMPRom Old369 ; endif ;>>>>>>>>>>> SubPinFillR rSubPin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld369 ;if not, skip tst.l d3 ;right to left? bmi.s UseOld369 ;if so, skip endif LEA SubPinHandler,A0 ;set up the handler BRA ArithFillCommon ;use comon code ;****************************************************************************************** ; Handle AddMax clipped rectangle fill if patchciRom THEN UseOld36B JMPRom Old36B ; endif ;>>>>>>>>>>> AddMaxFillR rMax8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld36B ;if not, skip tst.l d3 ;right to left? bmi.s UseOld36B ;if so, skip endif LEA AddMaxHandler,A0 ;set up the handler BRA ArithFillCommon ;use comon code ;****************************************************************************************** ; Handle AddMin clipped rectangle fill if patchciRom THEN UseOld36D JMPRom Old36D ; endif ;>>>>>>>>>>> AddMinFillR rMin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld36D ;if not, skip tst.l d3 ;right to left? bmi.s UseOld36D ;if so, skip endif LEA AddMinHandler,A0 ;set up the handler BRA ArithFillCommon ;use comon code ;****************************************************************************************** ; Handle Blend clipped rectangle fill if patchciRom THEN UseOld366 JMPRom Old366 ; endif ;>>>>>>>>>>> BlendFillR rAvg8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld366 ;if not, skip tst.l d3 ;right to left? bmi.s UseOld366 ;if s0, skip endif LEA BlendHandler,A0 ;set up the handler BRA ArithFillCommon ;use comon code ;****************************************************************************************** ; Now we start on the arithmetic fills for unclipped rectangles. Use the common ; scan line handler for ovals/rrects to save code. ; First we handle AddOver mode, unclipped if patchciRom THEN UseOld352 JMPRom Old352 ; endif ;>>>>>>>>>>> AddOverUnClip bAddOver8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld352 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld352 ;if so, skip endif LEA AddOverHandler,A0 ;set up the handler ArithUCCommon MOVE.L A0,-(SP) ;remember handler address ; set up the registers and invoke the common scan-line handler SUB.L A2,A2 ;no region pointer ASR #3,D6 ;bit index to byte index MOVE.L A4,A3 ;set up pattern pointer MOVE.L A5,A1 ;set up destination ArithUCLoop MOVE.L FIRSTMASK(A6),D3 ;set up left edge MOVE.L LASTMASK(A6),D1 ;set up right edge ; compute the count from the three pieces: left, mid and right MOVE.W LONGCNT(A6),D2 ;get left count BPL.S @3 ;if positive, we're cool MOVEQ #0,D2 ;only one word BRA.S @4 @3 ADD.W MIDCOUNT(A6),D2 ;add in the middle ADD.W PIXINLONG(A6),D2 ;add in the right ADDQ.W #2,D2 ;add for count bias LSR.W #2,D2 ;bytes -> longs @4 MOVE.L (SP),A0 ;get handler address ; call the appropriate handle, depending on whether the pattern is simple or complex CMP.W #8,PATROW(A6) ;is pattern real complex? BGT.S @0 ;if so, go handle it TST.B ENDSWITCH(A6) ;test pattern mode BMI.S @0 ;if bitmap, it's complex MOVE.L 0(A3,D6),D0 ;get left pattern EOR #4,D6 CMP.L 0(A3,D6),D0 ;left same as right? BEQ.S @1 ;if so, it's simple EOR #4,D6 ;restore D6 @0 MOVE.L A1,-(SP) BSR ArithComplex1 ;invoke scan-line handler for complex pats MOVE.L (SP)+,A1 BRA.S @2 @1 EOR #4,D6 MOVEM.L A1/A3,-(SP) BSR ArithSimplePat MOVEM.L (SP)+,A1/A3 ; bump pointers to next time, and loop until done @2 TST.B ENDSWITCH(A6) ;test pattern mode BEQ.S AFUCPat1 ;if zero, handle BMI.S AFUCBitMap1 ;if <0, go handle bitmap ; handle bumping the pattern pointers moveq #0,d0 ;patPos should be a long MOVE.W PATPOS(A6),D0 SUB.l D0,A3 ADD.W PATROW(A6),D0 AND.W PATVMASK(A6),D0 MOVE.W D0,PATPOS(A6) ADD.l D0,A3 BRA.S ArithUCNextLine ; handle second type of pattern AFUCPat1 MOVE.W PATPOS(A6),D0 ADDQ #1,D0 AND #15,D0 LEA ([EXPAT,A6],D0.W*4),A3 MOVE.W D0,PATPOS(A6) ; bump to the next scan line ArithUCNextLine MOVE.L PATOFFSET(A6),D6 ASR.L #3,D6 ;bits to bytes ArithUCNL2 ADD.W DSTROW+2(A6),A1 ;bump destination SUBQ.W #1,height(A6) BNE ArithUCLoop ADDQ #8,SP RTS ; handle unclipped blits source setup AFUCBitMap1 ADD.W D6,A3 ADD.W SRCBUMP(A6),A3 ;bump to next line MOVEQ #0,D6 BRA.S ArithUCNL2 ;****************************************************************************************** ; Handle SubOver unclipped rectangle fill if patchciRom THEN UseOld356 JMPRom Old356 ; endif ;>>>>>>>>>>> SubOverUnclip bSubOver8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld356 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld356 ;if so, skip endif LEA SubOverHandler,A0 ;set up the handler BRA ArithUCCommon ;use comon code ;****************************************************************************************** ; Handle AddPin unclipped rectangle fill if patchciRom THEN UseOld351 JMPRom Old351 ; endif ;>>>>>>>>>>> AddPinUnclip bAddPin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld351 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld351 ;if so, skip endif LEA AddPinHandler,A0 ;set up the handler BRA ArithUCCommon ;use comon code ;****************************************************************************************** ; Handle SubPin unclipped rectangle fill if patchciRom THEN UseOld353 JMPRom Old353 ; endif ;>>>>>>>>>>> SubPinUnclip bSubPin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld353 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld353 ;if so, skip endif LEA SubPinHandler,A0 ;set up the handler BRA ArithUCCommon ;use comon code ;****************************************************************************************** ; Handle AddMax unclipped rectangle fill if patchciRom THEN UseOld355 JMPRom Old355 ; endif ;>>>>>>>>>>> AddMaxUnclip bMax8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld355 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld355 ;if so, skip endif LEA AddMaxHandler,A0 ;set up the handler BRA ArithUCCommon ;use comon code ;****************************************************************************************** ; Handle AddMin unclipped rectangle fill if patchciRom THEN UseOld357 JMPRom Old357 ; endif ;>>>>>>>>>>> AddMinUnclip bMin8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld357 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld357 ;if so, skip endif LEA AddMinHandler,A0 ;set up the handler BRA ArithUCCommon ;use comon code ;****************************************************************************************** ; Handle Blend unclipped rectangle fill if patchciRom THEN UseOld350 JMPRom Old350 ; endif ;>>>>>>>>>>> BlendUnclip bAvg8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld350 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld350 ;if so, skip endif LEA BlendHandler,A0 ;set up the handler BRA ArithUCCommon ;use comon code ;****************************************************************************************** ; Here's where we handle transparent mode. The basic strategy is to create a mask from ; the pattern (for one and two long patterns) so we don't have to keep examining it ; pixel by pixel. (If the mask is all ones, fall into the standard fills). ; the first one is for transparent mode for ovals and roundRects ;>>>>>>>>>>> TransFillO slTransparent8 if patchciRom THEN CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BEQ.S @0 ;if not, skip JMPRom Old38C ; endif @0 CMP.W #4,PATROW(A6) ;is it a simple pattern? BGT.S TransComplexPat ;if not, inspect it closer ; it's a simple pattern, so make a mask according to the see-through color TransSimple1 MOVE.L (A0),D6 ;fetch the pattern MOVEQ #-1,D4 ;mask is initially all ones MOVE.B TRANSCOLOR(A6),D5 ;get color to compare with CMP.B D6,D5 BNE.S @0 CLR.B D4 @0 ROR.L #8,D4 ROR.L #8,D6 CMP.B D6,D5 BNE.S @1 CLR.B D4 @1 ROR.L #8,D4 ROR.L #8,D6 CMP.B D6,D5 BNE.S @2 CLR.B D4 @2 ROR.L #8,D4 ROR.L #8,D6 CMP.B D6,D5 BNE.S @3 CLR.B D4 @3 ROR.L #8,D4 ROR.L #8,D6 ; if the mask is all ones, plot it quickly using the standard fill routine MOVE.L A2,D0 ;if no clipping BEQ.S @4 ;skip optimization (things not set up) CMP.L #-1,D4 ;is mask all ones? bne.s @4 ;no jmp ([$E00+$380*4]) ;yes, use standard pattern fill ; OK, mask is in D4, A2 points to the region, pattern in D6 and A1 is the destination. ; use the straightforward loop, since region optimizations aren't worth it since we ; always have to read the destination. @4 TST.W D2 ;only one long? BNE.S TransSimpleLoop ;if not, skip TSL0 AND.L D1,D3 ;combine edges for last one TransSimpleLoop MOVE.L A2,D0 BEQ.S @0 AND.L (A2)+,D3 ;pick up the region mask @0 AND.L D4,D3 ;punch out transparent part MOVE.L D6,D0 AND.L D3,D0 NOT.L D3 AND.L (A1),D3 OR.L D0,D3 MOVE.L D3,(A1)+ MOVEQ #-1,D3 SUBQ.W #1,D2 ;decrement counter BGT.S TransSimpleLoop ;loop until done BEQ.S TSL0 RTS ; see if the complex pattern is really a simple one, if so, we can speed things up TransComplexPat MOVE.W PATHPOS(A6),D6 ; ASR.W #3,D6 ;turn bits back into bytes ADD.W D0,D6 ; MOVE.W PATHMASK(A6),D4 ;get pattern mask ASR #3,D4 ;turn bit index to byte index AND.W D4,D6 ;mask it MOVE.L EXPAT(A6),A3 ADD.l PATVPOS(A6),A3 ;compute pattern address CMP.W #8,PATROW(A6) ;is it a double pattern? BGT.S TransComplex1 ;if not, must be complex MOVE.L 0(A3,D6),D4 ;get source longword EOR #4,D6 CMP.L 0(A3,D6),D4 ;is it really simple? BEQ TransSimple1 ;if so, go handle EOR #4,D6 ;restore D6 TransComplex1 MOVE.L D7,-(SP) MOVE.L TRANSCOLOR(A6),D5 ;get color to compare with TST.W D2 BNE.S TCPatLoop ; it's complex, so plot it ourselves. First fetch the pattern. TCPLoop0 AND.L D1,D3 TCPatLoop MOVE.W PATHMASK(A6),D4 ;get pattern mask ASR #3,D4 ;turn bit index to byte index AND.W D4,D6 ;mask it MOVE.L 0(A3,D6),D7 ;get source longword ADDQ #4,D6 CMP.L D7,D5 ;all transparent? BEQ.S TCPSkip ; now create a mask for it MOVEQ #-1,D4 ;mask is initially all ones CMP.B D7,D5 BNE.S @0 CLR.B D4 @0 ROR.L #8,D4 ROR.L #8,D7 CMP.B D7,D5 BNE.S @1 CLR.B D4 @1 ROR.L #8,D4 ROR.L #8,D7 CMP.B D7,D5 BNE.S @2 CLR.B D4 @2 ROR.L #8,D4 ROR.L #8,D7 CMP.B D7,D5 BNE.S @3 CLR.B D4 @3 ROR.L #8,D4 ROR.L #8,D7 ; now we can finally plot it MOVE.L A2,D0 BEQ.S @8 AND.L (A2)+,D3 ;pick up the region mask @8 AND.L D4,D3 ;punch out transparent part MOVE.L D7,D0 AND.L D3,D0 NOT.L D3 AND.L (A1),D3 OR.L D0,D3 MOVE.L D3,(A1)+ ; loop until done NextTCP MOVEQ #-1,D3 SUBQ.W #1,D2 ;decrement counter BGT.S TCPatLoop ;loop until done BEQ.S TCPLoop0 MOVE.L (SP)+,D7 RTS TCPSkip MOVE.L A2,D0 BEQ.S @0 ADDQ.L #4,A2 @0 ADDQ #4,A1 BRA.S NextTCP ;****************************************************************************************** ; Here's where we handle the clipped transparent mode rectangle fill ; if patchciRom THEN ; <5> if 0 THEN ; <5> UseOld36A JMPRom Old36A ; endif ;>>>>>>>>>>> TransFillR rTransparent8 ; if patchciRom THEN ; <5> if 0 THEN ; <5> CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld36A ;if not, skip tst.l d3 ;right to left? bmi.s UseOld36A ;if s0, skip endif ; set up the registers and invoke the common scan-line handler MOVE.L A4,A2 ;set up region pointer ASR #3,D6 ;bit index to byte index MOVE.L A5,A1 ;set up destination TransFillLoop MOVEQ #-1,D1 MOVEQ #-1,D3 ;edge masks all ones (edges in region) MOVE.W BUFSIZE(A6),D2 ;set up the count ADDQ #4,D2 ;make one based LSR.W #2,D2 SUBQ #1,D2 ;make zero based ; call the appropriate handle, depending on whether the pattern is simple or complex CMP.W #8,PATROW(A6) ;is pattern real complex? BGT.S @0 ;if so, go handle it TST.B endSwitch(A6) ;test pattern mode BMI.S @0 ;treat bitmap as complex MOVE.L 0(A3,D6),D0 ;get left pattern EOR #4,D6 CMP.L 0(A3,D6),D0 ;left same as right? BEQ.S @1 ;if so, it's simple EOR #4,D6 ;restore D6 @0 BSR TransComplex1 ;invoke scan-line handler for complex pats BRA.S @2 @1 EOR #4,D6 MOVE.L A3,A0 BSR TransSimple1 ; bump pointers to next time, and loop until done @2 moveq #0,d0 ;patPos should be a long MOVE.W patPos(A6),D0 TST.B endSwitch(A6) ;test pattern mode BEQ.S TransPat1 ;if zero, handle BMI.S TransBitMap1 ;if <0, go handle bitmap MOVE.L patOffset(A6),D6 ;get pattern index ASR.L #3,D6 ;bit index to byte index ; handle bumping the pattern pointers MOVE.L SRCADDR(A6),A3 ;set up pattern pointer SUB.l D0,A3 ADD.W PATROW(A6),D0 AND.W PATVMASK(A6),D0 MOVE.W D0,patPos(A6) ADD.l D0,A3 BRA.S TransSetPatPtr ; handle second type of pattern TransPat1 MOVE.L patOffset(A6),D6 ;get pattern index ASR.L #3,D6 ;bit index to byte index ADDQ #1,D0 AND #15,D0 LEA ([EXPAT,A6],D0.W*4),A3 MOVE.W D0,patPos(A6) TransSetPatPtr MOVE.L A3,SRCADDR(A6) ; bump to the next scan line TransFillNextLine MOVE.L DSTROW(A6),D0 ADD.L D0,DSTADDR(A6) MOVE.W VERT(A6),D0 ADD.W VBUMP(A6),D0 MOVE.W D0,VERT(A6) CMP.W LASTV(A6),D0 BNE.S @0 ; all done, so strip stack and return MOVE.L SAVESTK2(A6),A7 RTS ; set up registers and loop for the next line @0 MOVE.L SEEKMASK(A6),A0 JSR (A0) ;seek new region MOVE.L SRCADDR(A6),A3 ;set up pattern pointer MOVE.L DSTADDR(A6),A1 ;set up dest ptr MOVE.L RGNADDR(A6),A2 ;set up region ptr BRA TransFillLoop ; handle bumping the source if it's a bitmap TransBitMap1 MOVE.L SRCROW(A6),D0 ; ADD.L D0,SRCADDR(A6) MOVE.l patOffset(A6),D6 asr.l #3,d6 ;make byte offset BRA.S TransFillNextLine ;****************************************************************************************** ; if patchciRom THEN ; <5> if 0 THEN ; <5> UseOld354 JMPRom Old354 ; endif ;>>>>>>>>>>> TransUnClip bTransparent8 ; if patchciRom THEN ; <5> if 0 THEN ; <5> CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? BNE.S UseOld354 ;if not, skip tst.l (sp) ;right to left? bmi.s UseOld354 ;if so, skip endif ; set up the registers and invoke the common scan-line handler SUB.L A2,A2 ;no region pointer ASR #3,D6 ;bit index to byte index MOVE.L A4,A3 ;set up pattern pointer MOVE.L A5,A1 ;set up destination TransUCLoop MOVE.L FIRSTMASK(A6),D3 ;set up left edge MOVE.L LASTMASK(A6),D1 ;set up right edge ; compute the count from the three pieces: left, mid and right MOVE.W LONGCNT(A6),D2 ;get left count BPL.S @3 ;if positive, we're cool MOVEQ #0,D2 ;only one word BRA.S @4 @3 ADD.W MIDCOUNT(A6),D2 ;add in the middle ADD.W PIXINLONG(A6),D2 ;add in the right ADDQ.W #2,D2 ;add for count bias LSR.W #2,D2 ;bytes -> longs ; call the appropriate handle, depending on whether the pattern is simple or complex @4 CMP.W #8,PATROW(A6) ;is pattern real complex? BGT.S @0 ;if so, go handle it TST.B ENDSWITCH(A6) ;test pattern mode BMI.S @0 ;if bitmap, handle as complex MOVE.L 0(A3,D6),D0 ;get left pattern EOR #4,D6 CMP.L 0(A3,D6),D0 ;left same as right? BEQ.S @1 ;if so, it's simple EOR #4,D6 ;restore D6 @0 MOVE.L A1,-(SP) BSR TransComplex1 ;invoke scan-line handler for complex pats MOVE.L (SP)+,A1 BRA.S @2 @1 EOR #4,D6 MOVEM.L A1/A3,-(SP) MOVE.L A3,A0 BSR TransSimple1 MOVEM.L (SP)+,A1/A3 ; bump pointers to next time, and loop until done @2 TST.B ENDSWITCH(A6) ;test pattern mode BEQ.S TransUCPat1 ;if zero, handle BMI.S TransUCBitMap1 ;if <0, go handle bitmap ; handle bumping the pattern pointers moveq #0,d0 ;patPos should be a long MOVE.W PATPOS(A6),D0 SUB.l D0,A3 ADD.W PATROW(A6),D0 AND.W PATVMASK(A6),D0 MOVE.W D0,PATPOS(A6) ADD.l D0,A3 BRA.S TransUCNextLine ; handle second type of pattern TransUCPat1 MOVE.W PATPOS(A6),D0 ADDQ #1,D0 AND #15,D0 LEA ([EXPAT,A6],D0.W*4),A3 MOVE.W D0,PATPOS(A6) ; bump to the next scan line TransUCNextLine MOVE.L PATOFFSET(A6),D6 ASR.L #3,D6 ;bits to bytes TransUCNL2 ADD.W DSTROW+2(A6),A1 ;bump destination SUBQ.W #1,height(A6) BNE TransUCLoop ADDQ #4,SP RTS ; handle unclipped blits source setup TransUCBitMap1 ADD.W D6,A3 ADD.W SRCBUMP(A6),A3 ;bump to next line MOVEQ #0,D6 BRA.S TransUCNL2 ;****************************************************************************************** ; End of arithmetic transfer modes! ;****************************************************************************************** ENDPROC