;
;	File:		Stretch.a
;
;	Copyright:	© 1981-1993 by Apple Computer, Inc., all rights reserved.
;
;	Change History (most recent first):
;
;	   <SM5>	 9/12/93	SAM		Changed all instances of _Translate24to32 to _rTranslate24to32
;									so they can coditionalized out of the build.
;	   <SM4>	 7/16/92	CSS		Update from Reality:
;									<66> 6/25/92 SAH	#1033729: Fixed a bug where we don't always recognize when we're
;														drawing to the alpha channel (just before calling ScaleBlt). We
;														now do this correctly and take Stretch if drawing alpha,
;														otherwise take the faster loops in ScaleBlt (which zero out the
;														alpha channel).
;									<65> 6/10/92 SAH	Fixed a problem where we would defer to stretch if ScaleBlt did
;														not hande the copy and the src was greater than one bits deep.
;														This was causing crashes with Aldus Freehand and Macromind
;														Director. Also fixed a problem where Stretch would munge
;														StkLowPt, HieHeapMark and your stack in low-memory situations.
;									<64> 6/8/92	SAH		#1031825: Brought the ScaleBlt loops back to life. Now use
;														ScaleBlt for indexed to direct (16 and 32) as well as indexed to
;														indexed. Make use of new srcBlackWhiteOnly flag to enable us to
;														use BitBlt when this is set and the src and dst are the same
;														depths. Check to see if we need to change ScaleColor to
;														ColorizeInModeCase if ScaleBlt fails. Also, test if using an
;														alpha mode before calling ScaleBlt, in which case we take
;														stretch.
;	   <SM3>	 6/11/92	stb		<sm 6/9/92>stb Synch with QDciPatchROM.a; added comments to
;									StretchBits, MapModeTable, SRCONE, stNoStack, stMask0,
;									stMASK0Slow, stHilite, arith. transfer loops for 16 & 32
;									bits/pixel, OneColor, DoubleColor, QUADColor, EightLoop,
;									BWtoD15Alpha, BWtoD24Alpha, AverageH16, Dither32toIndexed,
;									Dither16toIndexed, Dither32toGray, Dither16toGray,
;									Dither16toBitmap, Search32to32, Search32toInd, SeedCFill32,
;									Search32to16, Search16toIndexed, SeedCFill16, Search16to32,
;									Search16to16.
;		<63>	  5/5/92	SAH		Put fix for clipped vertical stretch back in for Cube-E
;		<62>	 1/15/92	KC		Fix "Short branch to the next instruction changed to a NOP"
;									assembler warning.
;		<61>	 10/4/91	JSM		Change PsychoticFarmerOrLater conditionals to TheFuture.
;		<60>	 10/2/91	DTY		Conditionalise last changes for TheFuture.
;		<59>	 10/2/91	KON		Fix bug where CopyBits was crashing when vertically stretching a
;									pixmap that is clipped at the top.
;		<58>	 10/2/91	KON		Save and restore stklowPt (rather than just setting it to sp on
;									exit) in stretch.  This fixes a bug where someone turns off the
;									stack sniffer and then calls stretch which turns it back on.
;									Also, abort picture playback when QDError = AbortPicPlayBackErr.
;		<57>	 10/2/91	KON		Save and restore stklowPt (rather than just setting it to sp on
;									exit) in stretch. This fixes a bug where someone turns off the
;									stack sniffer and then calls stretch which turns it back on.
;									Abort picture playback when QDError = AbortPicPlayBackErr.
;		<56>	 9/13/91	DTY		Conditionalise previous change so it doesnÕt get built for
;									CubeE. (ItÕll get built for PsychoticFarmerAndLater.)  Move in
;									code that was taken out between <54> and <55>, and build it for
;									CubeE only.
;		<55>	 7/23/91	KON		Speed up indexed to 32-bit srcCopy mode.  Speed up colorized
;									text:  don't take scale case when depths are the same.
;		<54>	 3/19/91	KON		DTY, WRKSHT#SAH-QD-055: Some pixmaps created with an old version
;									of ResEdit had the high bit of pmVersion set. This causes the
;									pmVersion macro to crash, so I removed it.
;		<53>	 3/18/91	KON		GSC and JT: WKSHT# SAH-QD-054 16-bit source shrinks crash
;									because the average buffer is calculated from the promoted
;									depth, rather than the real depth.
;		<52>	  3/6/91	KON		CEL: BRC# 84369 Register D0 was getting trashed when search
;									procs were attached to direct destinations.  Also, color
;									calculation for 16-bits was incorrect when search proc is
;									installed.
;		<51>	 2/19/91	KON		DDG: WorkSheet #KS-003, MaskAddr in stackframe is not
;									initialized if there is not a mask. This was causing crashes in
;									some cases since verticle merge scanline routines look at the
;									maskaddr.
;		<50>	 1/25/91	KON		DDG: BRC# 81625, A fix in QDciPatchROM.a required reorganizing
;									part of stretch. This change keeps the files in synchronization.
;		<49>	 1/23/91	KON		Optimize and clean up code that was rushed for B4. [SMC]
;		<48>	 1/14/91	KON		Fix PixMaps with nil color tables and CopyDeepMask with 1-bit
;									mask.  Fix bug in pmVersion macro. [SMC]
;		<47>	 1/11/91	KON		Register was getting trashed around call to SeekMask. This
;									caused CopyBits with more 3 regions to get trashed as in the
;									KeyCaps CDEV. [DDG]
;		<46>	12/17/90	KON		Fix one of the problems with NIL color tables. [smc]
;		<45>	11/26/90	SMC		Fixed pattern hilite once and for all, and forced arithmetic
;									transfers to direct devices into rgnblt instead of the slower
;									loops in bitblt.  With BAL.
;		<44>	11/12/90	KON		Fix problem with colorizing when dithering from an indexed src
;									to an indexed destination. [smc]
;		<43>	 11/9/90	KON		Copy rectangles to local stack and fixed problems with negative
;									pmVersions.
;		<42>	10/31/90	SMC		Fixed alpha channel bugs with BAL.
;		<41>	 9/25/90	KON		If source is 1-bit black and white and we are not shrinking,
;									clear dither bit. (With SMC).
;		<40>	 9/18/90	SMC		Fix transparent, addMax, subOver, and addMin transfers with a
;									pattern.
;		<39>	 9/18/90	BG		Removed <25>. 040s are behaving more reliably now.
;		<38>	 9/14/90	SMC		Commented out all of the QuickerDraw routines and changed the
;									logic to send those cases through ScaleBlt which are now faster
;									and smaller (by about 1K). This implicitly fixes a bus error
;									problem under AU/X when scaling from a 1-bit screen to the left
;									edge of an 8-bit screen.
;		<37>	 9/13/90	KON		NEEDED FOR BETA:  Fix problem where promoting source to RGB is
;									messed up. This showed up when the source is 1-bit.  Also fixed
;									in QDciPatchROM.a.
;		<36>	 9/10/90	KON		Fixed one-bit to one-bit colorized copy.
;		<35>	  9/6/90	KON		Fix 16 to indexed search loop.
;		<34>	  9/5/90	KON		Fix copymask from an indexed src. The pmtable was not set
;									correctly.
;		<33>	  9/4/90	KON		fix problem where ctseed for 1-bit sources was getting trashed.
;									If direct destination and search proc installed, use versions of
;									fg and bg colors which have not been changed by the proc to do
;									colorizing.
;		<32>	 8/26/90	KON		Fix Search16to32 and Search32to16 stack frame referencing.  Add
;									32-bit clean versions of MaskPixPmTable and SrcPixPmTable to
;									stack frame.
;		<31>	 8/21/90	KON		Always call search proc if one exists. If search proc fails,
;									still use search procs RGBColor.  Replicate bits when passing
;									16-bit source color to search procs.
;		<30>	 8/15/90	KON		Fixed transparent mode which was writing outside the destination
;									rectangle.  Turned off colorizing for arithmetic modes.
;		<29>	 7/23/90	KON		Fix CopyMask in cases where left and right edge are displaying
;									garbage.
;		<28>	 7/20/90	gbm		Change some identifiers to avoid assembly conflicts
;		<27>	 7/17/90	KON		Fix 16-bit source notCopy mode.
;		<26>	 7/10/90	KON		Fixed CopyMask for 16-bit sources, and cases where 16-bit masks
;									were failing.  Also fixed vertical shrinking of 1-bit sources.
;		<26>	  7/9/90	KON		Fixed CopyMask for 16-bit sources, and cases where16-bit masks
;									were failing.
;		<25>	 6/28/90	BG		Added EclipseNOPs for flakey 040s.
;		<24>	  6/5/90	KON		Speed up notCopy mode for direct src to direct dst by using
;									invert flag.
;		<23>	  6/4/90	KON		Speed things that slowed down up by checking if colorizing is a
;									nop.
;		<22>	 5/29/90	HJR		Fix Mac32 build problem by moving table8 and some code saving
;									mods.
;		<21>	 5/24/90	KON		Fix transfer modes for direct devices, and fix colorizing for
;									indexed devices.
;	   <19+>	 4/12/90	KON		Add deep masks for copymask.
;		<19>	 4/11/90	KON		Suppress colorizing in src blits when the src clut is nil (i.e.
;									the colors are a ramp between the foreground and background
;									colors.
;		<18>	 3/13/90	KON		Part of file got trashed.  Now fixed.
;		<17>	 3/13/90	KON		Fixed bug in 16-bit search proc.
;		<16>	  3/6/90	KON		Fixed error term for vertical shrinking so  expanding and then
;									shrinking by an integral amount does not alter the image.
;		<15>	 2/23/90	KON		Fixed buffer problem in Dither16toGray.
;		<14>	 2/23/90	KON		Fixed Dither32toGray and Dither16toGray. Random dots were
;									displayed because error term was not calculated right.
;		<13>	 2/23/90	KON		Added 16-bit shrink.
;		<12>	 2/16/90	KON		Cleared out high end of register of ErrBuf size calculation.
;		<11>	 2/14/90	KON		Try to get 256K in stNoStack. Memory requirement calculation now
;									use longs so high bits aren't lost. StackFree is updated
;									correctly.
;		<10>	 2/14/90	BAL		Changed MFTemp memory stack allocation to try for upto 128K
;									chunk.
;		 <9>	  2/9/90	BAL		Fixed dither 8-bit to 32-bit stretched copybits.
;		 <8>	  2/5/90	BAL		Fixed bug in vertical shrinking while performing indexed to
;									indexed dither.
;		 <7>	  2/1/90	BAL		Dither16toIndexed: Fix dither error calculation for 16 bit
;									sources being displayed on color indexed devices.
;		 <6>	  2/1/90	BAL		Special cased SeedCFill/CalcCMask search procs for 16 and 32 bit
;									sources.
;		 <5>	 1/30/90	BAL		Fixed bugs in underflow of error when dithering to a grayscale
;									or bitmap destination. This affects Dither32toGray/Bitmap and
;									Dither16toGray/Bitmap.
;		 <4>	 1/28/90	KON		Fix clipping when destination is clipped at the top.
;		 <3>	 1/28/90	BAL		Added the depth conversion routines Dither32toBitmap and
;									Dither16toBitmap and changed the decision tree to utilize them.
;		<1+>	  1/3/90	BAL		FOR 6.0.5:  Submitted latest version to BBS.  Changes include
;									indexed to indexed dithering support.
;	   <1.9>	 12/9/89	BAL		Fixed bug in accumulation of dither error in some of the loops.
;									Should fix in others. Fixed a bug and optimized the case of
;									source rects with tops above srcbits.bounds.
;	   <1.8>	 9/25/89	BAL		Changed "NOT forROM" conditionals to "useColorICON" and
;									defaulted it to false
;	   <1.7>	 7/16/89	GGD		GGD for the vacationing BAL, Fixed bug in AverageH when
;									averaging 2 pixels, and optimized the entire loop at the same
;									time.
;	  <¥1.6>	 7/14/89	BAL		For Aurora: Final CQD
;	   <1.5>	 6/30/89	BAL		Make A5 valid and return to 24 bit mode before calling search
;									procs
;	  <¥1.4>	 5/29/89	BAL		Blasting in 32-Bit QuickDraw version 1.0 Final
;				 5/26/89	BAL		Fixed bug in call to MakeITable if seed mismatch during direct
;									to indexed copy.
;	  <¥1.3>	 4/12/89	BAL		Blasting in 32-Bit QuickDraw 1.0B1
;				 9/26/88	BAL		Replace successfully TrimRect'ed rgns with wideopen to avoid
;									multiple Trims.
;				 9/22/88	BAL		Moved initialization of region state records into GetSeek.
;				 9/19/88	BAL		Altered to use common stack frame file 'Drawing Vars.a'
;				 9/18/88	BAL		Altered to get CRSRFLAG value from _BitsToPix; Removed
;									references to PIXSRC;
;				  9/4/88	BAL		Added area averaging for shrinking of 32 bit pixmaps.
;				 8/29/88	BAL		Changed 32 to 8-1bit dither to carry 2-D error.
;				 6/28/88	BAL		Added special scaling routine for B/W 1 bit to direct RGB in a
;									32 bit pixel.
;				 6/27/88	BAL		Changed pattern expansion routines for 16 and 32 bits to
;									optimize for solid.
;				 6/17/88	BAL		Added routines to depth scale from direct to indexed devices.
;				  5/9/88	BAL		Altered depth scaling code to use long sized pixel translation
;									table.
;				  5/4/88	BAL		fixed bug in n*8x scaling (n=3,5,6,7...)
;				  5/3/88	BAL		fixed 2 scaling bugs where word-sized operations overflowed
;				  4/9/88	BAL		altered to use 32bit addressing during blit to screens
;				 12/7/87	BAL		Changed <C947> to restore D7 (invertFlag) before returning to
;									rgn/bitBlt. <C983>
;				 11/8/87	BAL		Forced stretch to only do color table pixel translation if
;									absolutely necessary. <C947>
;				 11/8/87	BAL		Forced stretch to TrimRect(clipRgn,MinRect) before submitting to
;									rgnBlt. <C951>
;				 11/8/87	BAL		Fixed computation of bufSize for more accurate region clipping
;									at at depths greater than 1. <C954>
;				  2/3/87	EHB		Added error checking
;				  1/3/87	CRC		expect color param in stretch
;				12/12/86	CRC		Added arithmetic modes
;				 10/9/86	EHB		Added mask parameters to stretchbits calls
;				 9/11/86	EHB		Added depth translation (N-bit to M-bit)
;				  9/8/86	EHB		Added full-ratio color scaling (N-bit to N-bit)
;				 7/29/86	EHB		Allocate EXPAT buffer on stack so long aligned
;				 7/26/86	EHB		Added support for expanded patterns
;				 7/22/86	EHB		Pass MODE to PatExpand for colorizing
;				  7/7/86	EHB		Revised use of color in blt routines.
;				  7/5/86	EHB		Replaced SeekMask and GetXRtn with GetSeek
;				 6/24/86	EHB		Big re-org: Create one stack frame shared by stretch, rgnblt,
;									bitblt Set up all shared locals here, then call rgnblt, bitblt
;									with parms in stack frame and registers (since stretchbits
;									called from everywhere).
;				 6/23/86	EHB		Rearranged for shared stack frame between stretch, rgnblt,
;									bitblt Set up all common fields before calls to rgnblt Removed
;									all parameters passed to rgnblt (only called from here)
;				 6/21/86	EHB		Do expansion in 2 passes: one for data, next for chunks
;				 6/20/86	EHB		New params to COLORMAP Added FCOLOR and BCOLOR to stack frame
;				 6/19/86	EHB		Use longs in horiz calculations for big pixels
;				 6/18/86	EHB		Take depth into account for scaling
;				 6/18/86	EHB		Added a pattern param so it can be called instead of RgnBlt
;				 6/16/86	EHB		Added routine GetSizeShift to avoid multiplies
;				 6/15/86	EHB		Convert BitsToPix, and use pixelSize
;				 6/14/86	EHB		Call GetXRtn to set expand routine for SeekMask Changed
;									SRCBITS/DSTBITS to SRCPIX/DSTPIX
;				 6/13/86	EHB		Moved SeekMask to another file Rearranged stack frame with
;									SeekMask stuff at top
;				 6/11/86	EHB		Modified Stretch to use longwords and 020 instructions Made sure
;									that stack buffers all longword aligned
;				  6/5/86	EHB		Masked off flag bits in all references to rowBytes
;
;	To Do:
;
		BLANKS	ON
		STRING	ASIS

		MACHINE MC68020

;------------------------------------------------------------------
;
;  -->	STRETCH.TEXT
;
;  TO DO:  TWO IDENTICAL EXPAND ROUTINES IS TOO MUCH!!!
;
;------------------------------------------------------------------
;
;	MODIFICATIONS
;
;	5Jun86	EHB		Masked off flag bits in all references to rowBytes
;  11Jun86 	EHB		Modified Stretch to use longwords and 020 instructions
;					Made sure that stack buffers all longword aligned
;  13Jun86  EHB		Moved SeekMask to another file
;					Rearranged stack frame with SeekMask stuff at top
;  14Jun86  EHB		Call GetXRtn to set expand routine for SeekMask
;					Changed SRCBITS/DSTBITS to SRCPIX/DSTPIX
;  15Jun86  EHB		Convert BitsToPix, and use pixelSize
;  16Jun86  EHB		Added routine GetSizeShift to avoid multiplies
;  18Jun86  EHB		Take depth into account for scaling
;  18Jun86  EHB		Added a pattern param so it can be called instead of RgnBlt
;  19Jun86	EHB		Use longs in horiz calculations for big pixels
;  20Jun86	EHB		New params to COLORMAP
;					Added FCOLOR and BCOLOR to stack frame
;  21Jun86  EHB		Do expansion in 2 passes: 32 for data, next for chunks
;  23Jun86  EHB		Rearranged for shared stack frame between stretch, rgnblt, bitblt
;					Set up all common fields before calls to rgnblt
;					Removed all parameters passed to rgnblt (only called from here)
;  24Jun86  EHB		Big re-org:  Create one stack frame shared by stretch, rgnblt, bitblt
;					Set up all shared locals here, then call rgnblt, bitblt with parms
;					in stack frame and registers (since stretchbits called from everywhere).
;	5Jul86	EHB		Replaced SeekMask and GetXRtn with GetSeek
;   7Jul86  EHB		Revised use of color in blt routines.
;  22Jul86  EHB		Pass MODE to PatExpand for colorizing
;  26Jul86	EHB		Added support for expanded patterns
;  29Jul86  EHB     Allocate EXPAT buffer on stack so long aligned
;   8Sep86  EHB		Added full-ratio color scaling (N-bit to N-bit)
;  11Sep86  EHB		Added depth translation (N-bit to M-bit)
;   9Oct86  EHB		Added mask parameters to stretchbits calls
;  12Dec86  CRC		Added arithmetic modes
;	3Jan87	CRC		expect color param in stretch
;   3Feb87  EHB		Added error checking
;
;________________________________ Post Mac II _____________________________________
;
;  08Nov87  BAL     Forced stretch to only do color table pixel translation if
;					absolutely necessary. <C947>
;  08Nov87  BAL     Forced stretch to TrimRect(clipRgn,MinRect) before submitting to rgnBlt. <C951>
;  08Nov87  BAL		Fixed computation of bufSize for more accurate region clipping at
;					at depths greater than 1.  <C954>
;  07Dec87  BAL		Changed <C947> to restore D7 (invertFlag) before returning to rgn/bitBlt. <C983>
;  09Apr88  BAL		altered to use 32bit addressing during blit to screens
;  03May88  BAL		fixed 2 scaling bugs where word-sized operations overflowed
;  04May88  BAL		fixed bug in n*8x scaling (n=3,5,6,7...) 
;  09May88	BAL 	Altered depth scaling code to use long sized pixel translation table.
;  17Jun88	BAL 	Added routines to depth scale from direct to indexed devices.
;  27Jun88	BAL 	Changed pattern expansion routines for 16 and 32 bits to optimize for solid.
;  28Jun88	BAL 	Added special scaling routine for B/W 1 bit to direct RGB in a 32 bit pixel.
;  29Aug88	BAL 	Changed 32 to 8-1bit dither to carry 2-D error.
;  04Sep88	BAL 	Added area averaging for shrinking of 32 bit pixmaps.
;  18Sep88	BAL 	Altered to get CRSRFLAG value from _BitsToPix;  Removed references to PIXSRC;
;  19Sep88 	BAL		Altered to use common stack frame file 'Drawing Vars.a'
;  22Sep88 	BAL		Moved initialization of region state records into GetSeek.
;  26Sep88 	BAL		Replace successfully TrimRect'ed rgns with wideopen to avoid multiple Trims.
;
;________________________________ Post Jackson Pollack _____________________________________
;
;  26May89	BAL		Fixed bug in call to MakeITable if seed mismatch during direct to indexed copy.

;
;	Output:  A3 contains address of current scanline.
;
		MACRO
		_pmVersion
	if 0 then
		cmp.l	maskaddr(a6),a3
		bne.s	@CheckSrc
		add.l	a5,a3							;bump mask to next row
		tst.w	maskpix+pmVersion(a6)
		bpl.s	@DoLittle
		move.l	a0,-(sp)
		move.l	maskpix+baseaddr(a6),a0
		jsr		(a0)
		move.l	(sp)+,a0
		move.l	a3,maskaddr(a6)
		bra.s	@DoLittle
@CheckSrc
;must be src.
	endif
		add.l	a5,a3							;bump src to next row
	if 0 then
		tst.w	srcpix+pmVersion(a6)
		bpl.s	@DoLittle
		move.l	a0,-(sp)
		move.l	srcpix+baseaddr(a6),a0
		jsr		(a0)
		move.l	(sp)+,a0
@DoLittle
	endif
		ENDM

;
; The first time bruce is called, D3 contains the starting scan line number
;  On output: A3 contains first scanline address
;
		MACRO
		_pmVersionSrcFirstTime
	if 0 then
		tst.w	srcpix+pmVersion(a6)
		bpl.s	@NoSrcPmVersion
		move.l	a0,-(sp)
		move.l	srcpix+baseaddr(a6),a0
		jsr		(a0)
		move.l	(sp)+,a0
@NoSrcPmVersion
	endif
		ENDM

		MACRO
		_pmVersionMaskFirstTime
	if 0 then
		tst.l	maskbits(a6)				;is there a mask?
		bne.s	@DoIt
		moveq	#0,a3						;init MaskAddr to zero	<KON 19FEB91>
		bra.s	@WriteIt
@DoIt
		tst.w	maskpix+pmVersion(a6)
		bpl.s	@DoLittle
		move.l	a0,-(sp)
		move.l	srcpix+baseaddr(a6),a0
		jsr		(a0)
		move.l	(sp)+,a0
@WriteIt
		move.l	a3,maskaddr(a6)				;a3 is returned by the routine
@DoLittle
	endif
		ENDM

StretchBits PROC  EXPORT
  		IMPORT Scale32toIndexed, Scale16toIndexed, ScaleIndexedToIndexed, Scale32ToBitMap
  		IMPORT Scale32toGray, Scale16toGray, Scale32to16, Scale16to32, Scale16ToBitMap
		IMPORT Search32toIndexed, Search16toIndexed, Search32to16, Search16to32
		IMPORT Dither32toIndexed, Dither16toIndexed, Dither32toGray, Dither16toGray
		IMPORT CB8to8Clip, CB8to1Clip, CB1to8Clip, Dither32toBitmap, Dither16toBitmap
		IMPORT scaleBlt, Search32to32, Search16to16
		IMPORT SHFTTBL
		EXPORT stMASK0, stMASK1, stMASK2, stMASK3, stAvg, stAddPin, stAddOver
		EXPORT stSubPin, stTransparent, stMax, stSubOver, stMin, stHilite
	    EXPORT Table2,TABLE4,TABLE8, setUpStretch, stNoStack
	    EXPORT stArith16Tab,stArith32Tab,stColorTab,stGrayTab,stSearchTab
	    EXPORT EXTBL,PATEXTBL,DoneStretch,OneBitProc,BlitCase,stScanLoop
		EXPORT NOPfgColorTable

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb
;--------------------------------------------------------------
;
;  PROCEDURE StretchBits(srcBits,maskBits,dstBits: BitMap;
;			 srcRect,maskRect,dstRect: Rect;
;			 mode: INTEGER; pat: Pattern;
;			 rgnA,rgnB,rgnC:  RgnHandle);
;
;  Transfer a rectangle of bits from srcBits to dstBits,
;  stretching or compressing according to srcRect and dstRect.
;  The transfer is clipped to the intersection of rgnA, rgnB, and rgnC.
;  It is also clipped to the specified mask.  If MaskBits is NIL, then
;  no masking is done.
;
;  Restrictions:
;
;	  if numer <> denom, then src and dst bitmaps do not overlap.
;
;
;  COPYRIGHT APPLE COMPUTER INC.
;  DESIGNED AND WRITTEN BY BILL ATKINSON
;


;----------------------------------------------------
;
;  A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE		EQU 	44					;SIZE OF PARAMETERS
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
PAT 			EQU 	MODE-4				;LONG, ADDR OF PATTERN
RGNA			EQU 	PAT-4				;LONG, RGNHANDLE
RGNB			EQU 	RGNA-4				;LONG, RGNHANDLE
RGNC			EQU 	RGNB-4				;LONG, RGNHANDLE
multColor		EQU		RGNC-2				;byte, set if source contains nonblack/white colors

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


	IF (&TYPE('useColorICON') = 'UNDEFINED') THEN
useColorICON	EQU		0
	ENDIF


;----------------------------------------------------

		LINK	A6,#VARSIZE 				;ALLOCATE LOCAL VARIABLES
		MOVEM.L D0-D7/A1-A5,-(SP)			;SAVE REGS
		MOVE.L	SP,SAVESTK(A6)				;REMEMBER STACK FOR LATER
		move.l	stklowPt,saveStkLowPt(a6)	;keep track of the sniffer	<57>
;
; Copy rectangles to stack since they might be part of a handle and could move.
; Some people don't know that CopyBits moves memory... just call me SlowDraw.
;	<KON 7NOV90>
;
		move.l	srcrect(a6),a0
		lea		newSrcRect(a6),a1
		move.l	a1,srcrect(a6)
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+

		move.l	maskrect(a6),a0
		lea		newMaskRect(a6),a1
		move.l	a1,maskrect(a6)
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+

		move.l	dstrect(a6),a0
		lea		newDstRect(a6),a1
		move.l	a1,dstrect(a6)
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+

		MOVE.W	MODE(A6),D1					;get mode							<42>
		BTST	#3,D1						;pattern mode?						<42>
		BNE.S	@0							;yes, alpha already stripped		<42>
		_GetStreamMode						;get alpha mode bits				<42>
		MOVE.W	D1,MODE(A6)					;save stripped mode					<42>
	@0:	MOVE.L	A5,SAVEA5(A6)				;REMEMBER GLOBAL POINTER
		move.b	mmu32Bit,MMUSave(a6)		;save mmu mode for cheap exit
		CLR.L	DSTMASKBUF(A6)				;ASSUME NO MASK
		CLR.L	stackHandle(A6)				;init alternate stack not used

;----------------------------------------------------------------
;
;  MAKE SURE THE STACK IS ON A LONGWORD BOUNDARY (FOR FAST BUFFERS)
;
		MOVE.L	SP,D1						;GET THE STACK POINTER
		AND.B	#$FC,D1						;FORCE LONG ALIGNMENT
		MOVE.L	D1,SP						;USE IT

;----------------------------------------------------
;
;  CONVERT SRCBITS AND DSTBITS TO PIXMAPS
;		(A5 must contain global ptr)
;
;  BITSTOPIX TAKES DEFAULT DEVICE FROM THEGDEVICE

		MOVE.L	THEGDEVICE,-(SP)			;SAVE THEGDEVICE
		MOVE.L	SRCDEVICE,THEGDEVICE		;SET UP SRC DEVICE
		MOVE.L	SRCBITS(A6),A1				;GET POINTER TO SRCBITS


	IF useColorICON THEN

	;----------------------------------------------------
	; SLIMEY HACK to draw Jackson Pollack Icon in Full Color:
	;
		move.l	baseAddr(a1),d0				;get baseAddr
		_rTranslate24To32					;clean up the address
		clr.w	filler2(a6)					;set myIcon flag false
		tst.l	d0							;is it in slot space?
		bmi.s	@1							;yes, skip chk 
		move.l	d0,a0						;to prevent Bus Errors
	;	cmp.l	#$EBF557E2,108(a0)			;check for race car signature
	;	cmp.l	#$cc45c929,108(a0)			;check for painting signature
		lea		80(a0),a0					;point into data
		cmp.l	#$842ba003,(a0)+			;check for prism signature
		bne.s	@1
		cmp.l	#$8445d455,(a0)+			;check for prism signature
		bne.s	@1
		cmp.l	#$8882e803,(a0)+			;check for prism signature
		bne.s	@1
		cmp.l	#$89017855,(a0)				;check for prism signature
		bne.s	@1

		move.l	jpCicn,a1					; get cicn handle
		move.l	(a1),a1						; point at pixmap
		move.l	(sp),a0						; get the dst gdevice handle
		move.l	(a0),a0						; point to it
		move.l	gdPMap(a0),a0				; get its pixmap handle
		move.l	(a0),a0						; point to it
		cmp.w	#4,pixelsize(a0)			; check depth
		bge.s	@usePMap					; 4 bit or deeper-> use pixmap data
		add		#IconBMap,a1				; else use bitmap data
		sub		#1,filler2(a6)				; using bitmap, don't hack colors

@usePMap
		cmp.w	#3,Mode(a6)					; BIC mode?
		bne.s	@2							; no, draw the icon
		bra		done


@2		clr.w	Mode(a6)					; use copy mode
		add		#1,filler2(a6)				; flag hack in progress
	;
	;----------------------------------------------------

	ENDIF


@1		LEA		SRCPIX(A6),A2				;COPY INTO SRCPIX
		_BitsToPix							;BITMAP -> PIXMAP

		MOVE.L	(SP)+,THEGDEVICE			;RESTORE THEGDEVICE AS DST DEVICE
		MOVE.L	DSTBITS(A6),A1				;GET POINTER TO DSTBITS
		LEA		DSTPIX(A6),A2				;COPY INTO DSTPIX
		_BitsToPix							;BITMAP -> PIXMAP
		MOVE.L	D1,REALBOUNDS(A6)			;SAVE REAL DST BOUNDS.TOPLEFT
		MOVE.B	D2,CRSRFLAG(A6)				;REMEMBER IF DST IS SCREEN 			<BAL 18Sep88>

;----------------------------------------------------
;
;  GET SHIFT AMOUNTS FOR SRC (D3) AND DST (D4) DEPTHS
;  THE PIXSRC FLAG IS SET IF SRC IS A PIXMAP THAT ISN'T ONE BIT PER PIXEL
;
		LEA		SHFTTBL,A0					;POINT TO SHIFT TABLE
		MOVE	SRCPIX+PIXELSIZE(A6),D0		;GET SRC PIXEL SIZE
		MOVEQ	#0,D3						;DEFAULT SHIFT = 0
		MOVE.B	0(A0,D0),D3					;GET SRC SHIFT
		MOVE	D3,SRCSHIFT(A6)				;AND SAVE SRC SHIFT AMOUNT

		MOVE	DSTPIX+PIXELSIZE(A6),D0		;GET DST PIXEL SIZE
		MOVEQ	#0,D4						;DEFAULT SHIFT = 0
		MOVE.B	0(A0,D0),D4					;GET DST SHIFT
		MOVE	D4,DSTSHIFT(A6)				;AND SAVE DST SHIFT AMOUNT

;----------------------------------------------------
;
;  CONVERT MASKBITS TO MASKPIX, AND GET SHIFT AMOUNT FOR MASK DEPTH
;  If mask is direct, pass depth through.  If mask is 2, 4, or 8 bit
;  promote mask to 32 bit/pixel.
;
		CLR		MASKSHIFT(A6)				;ASSUME DEPTH = 1
		MOVE.L	MASKBITS(A6),D0				;IS THERE A MASK?
		BEQ.S	NOMASK						;=>NO, SKIP MASK SETUP

		MOVE.L	D0,A1						;GET POINTER TO MASKBITS
		LEA		MASKPIX(A6),A2				;COPY INTO MASKPIX
		_BitsToPix							;BITMAP -> PIXMAP

		LEA		SHFTTBL,A0					;POINT TO SHIFT TABLE
		MOVE	MASKPIX+PIXELSIZE(A6),D0	;GET MASK PIXEL SIZE
		moveq	#0,d5						;default shift=0
		move.b	0(a0,d0),d5
		bne.s	@PromoteIt					;mask is 1-bit/pixel
;
; should promote 1-bit masks unless it's copy mode
;
		move.w	MODE(A6),d0					;COPY MODE and 1-bit deep?
		and.w	#$37,d0						;mask pattern and dither bits
		beq.s	NoMask						;yes, don't promote it
@PromoteIt
		cmp.b	#4,d5						;if it's 16 bpp, save mask depth
		beq.s	@gotMaskDepth
		move	#5,d5						;otherwise force it to 32 bits/pixel
@gotMaskDepth
		move	d5,maskshift(a6)

NOMASK

;-------------------------------------------------------------------
;
;  CALC MINRECT = INTERSECTION OF DSTRECT, DSTBITS.BOUNDS, AND THREE
;  REGION BOUNDING BOXES.  QUIT IF THE INTERSECTION IS EMPTY.
;
		MOVE.L	DSTRECT(A6),-(SP)			;PUSH ADDR OF DSTRECT
		PEA 	DSTPIX+BOUNDS(A6)			;PUSH ADDR OF DSTPIX.BOUNDS
		MOVE.L	RGNA(A6),A0 				;GET RGNHANDLE
		MOVE.L	(A0),A0 					;DE-REFERENCE IT
		PEA 	RGNBBOX(A0) 				;PUSH RGN BBOX
		MOVE.L	RGNB(A6),A0 				;GET RGNHANDLE
		MOVE.L	(A0),A0 					;DE-REFERENCE IT
		PEA 	RGNBBOX(A0) 				;PUSH RGN BBOX
		MOVE.L	RGNC(A6),A0 				;GET RGNHANDLE
		MOVE.L	(A0),A0 					;DE-REFERENCE IT
		PEA 	RGNBBOX(A0) 				;PUSH RGN BBOX
		MOVE	#5,-(SP)					;PUSH NRECTS
		PEA 	MINRECT(A6) 				;PUSH WHERE TO PUT RESULT
		_RSECT								;INTERSECT ALL RECTS
		BEQ 	GOHOME						;QUIT IF RESULT IS EMPTY


;----------------------------------------------------------------
;
;  SET UP NEWPATTERN TO INDICATE OLD OR NEW STYLE PATTERN
;  ALSO SET UP LOCAL PATTERN POINTER, LOCPAT(A6)
;
		MOVE.L	PAT(A6),LOCPAT(A6)			;COPY PATTERN POINTER
		MOVE	MODE(A6),LOCMODE(A6)		;COPY MODE
		TST		([DSTBITS,A6],ROWBYTES)		;IS THE DST OLD OR NEW?
		SMI		NEWPATTERN(A6)				;FLAG = TRUE IF NEW PATTERN
		CLR		PATROW(A6)					;FLAG NOT DOING BIG PATTERNS

		bclr	#6,LocMode+1(a6)			;clear dither bit			 <07Jul88 BAL>
		sne		useDither(a6)				;remember whether it was set <07Jul88 BAL>

;----------------------------------------------------------------
;
;  ADJUST MODE AND PATTERN FOR COLOR SEPARATION.
;		(A5 must contain global ptr)
;
		btst	#1,multColor+1(a6)			;check if src is a color font		<05JUNE92 SAH>
		sne		multiColor(a6)				;set multiColor flag for ColorMap
		_COLORMAP							;ALTER FOR COLOR SEPARATION

;---------------------------------------
;
;  SET UP INVERT FLAG IN D7 TO REFLECT MODE BIT 2
;  CHECK TO SEE IF PATTERN WILL BE USED
;
		MOVE	LOCMODE(A6),D2 				;GET TRANSFER MODE

	IF useColorICON THEN

		tst		filler2(a6)					;cicn hack
		beq.s	@1
		cmp		#8,srcPix+pixelSize(a6)	;8-bit clut on icon?
		bne.s	@1
		lea		srcPix+pmtable(a6),a0		;pnt to pmtable handle
		move.l	(a0),a0						;get handle
		move.l	(a0),a0						;pnt to table
		pea		ctTable+rgb+red(a0)			;push address of entry zero (white)
		pea		255*8+ctTable+rgb+red(a0)	;push address of entry 255 (black)
		_GetForeColor						;fill in entry 255
		_GetBackColor						;fill in entry zero
		MOVE	LOCMODE(A6),D2 				;restore TRANSFER MODE
@1
	ENDIF


;--------------------------------------------------------------
;
;	Use table lookup to map input mode, src type, and dst type
;	to a new mode, colorize location, swap fg/bk, use stretch (slow)
;	and whether or not to invert.
;
;	Index value is five bits: SRCTYPE DSTTYPE MODE (3 bits)
;	For SRCTYPE and DSTTYPE 1 = direct, 0 = indexed
;		MODE is bottom 3 bits of mode
;
;	Lookup value is a byte: INVERT 0 STRETCH? SWAP FG/BG CLRXLATE NEWMODE
;	For INVERT, 1 means invert in blit loop, 0 means don't
;		STRETCH, 1 means go through stretch, 0 means fast case ok
;		SWAP FG/BG	1 means swap, 0 means don't
;		CLRXLATE	1 means colorize in blit loop, 0 means translate in makescaletable
;		NEWMODE		3 bits determine which blit loop to take
;
		moveq	#0,d0			;default for patterns and arithmetic modes

		btst	#3,d2						;is it a pattern mode?
		bne		DoPattern					;=>yes, don't remap mode

		btst	#5,d2			;is it a arithmetic mode?
		bne.s	@useCopyMode	;yes, pretend copy mode

		moveq	#7,d0			;prepare to get mode
		and.w	d2,d0			;get mode in bottom 3 bits
@useCopyMode
		cmp.w	#4,d4			;destination indexed?
		blt.s	@destind
		bset 	#3,d0			;set dest direct bit

@destind
		cmp.w	#4,d3			;src indexed?
		blt.s	@srcind
		bset	#4,d0			;set dest direct bit
@srcind
		lea		MapModeTable,a0
		move.w	(a0,d0*2),d0		;get table lookup value
		bra.s	skipTable		;temporary, move table later

ScaleColorBit	EQU		3
SwapFGBGBit		EQU		4
UseStretchBit	EQU		5
InvertItBit		EQU		7
ColorizeInModeCaseBit	EQU	8
ColorizeInSrcBufBit		EQU	9

InvertIt	EQU		1 << InvertItBit
UseStretch	EQU		1 << UseStretchBit
SwapFGBG	EQU		1 << SwapFGBGBit
ScaleColor	EQU		1 << ScaleColorBit			;colorize in make scale table
ColorizeInModeCase	EQU	1 << ColorizeInModeCaseBit
ColorizeInSrcBuf	EQU	1 << ColorizeInSrcBufBit

; from QDciPatchROM.a verbatim (with the exception of CubeE stuff put back in this file) <sm 6/9/92>stb
MapModeTable
;
; indexed src, indexed dst
;
		dc.w	ScaleColor + srcCopy		;
		dc.w	ColorizeInModeCase + srcOr		;
		dc.w	ColorizeInModeCase + srcXor	;
		dc.w	ColorizeInModeCase + srcBic	;
		dc.w	UseStretch + SwapFGBG + ScaleColor + SrcCopy
		dc.w	InvertIt + ColorizeInModeCase + notSrcOr		;
		dc.w	InvertIt + ColorizeInModeCase + notSrcXor		;
		dc.w	InvertIt + ColorizeInModeCase + notSrcBic		;

;
; indexed src, direct dst
;
		dc.w	ScaleColor + srcCopy  ;+ UseStretch +						 		<05JUNE92 SAH>
		dc.w	InvertIt + UseStretch + notSrcBic + SwapFGBG + ColorizeInModeCase
		dc.w	InvertIt + UseStretch + notSrcXor + SwapFGBG + ColorizeInModeCase
		dc.w	InvertIt + UseStretch + notSrcOr + SwapFGBG + ColorizeInModeCase
		dc.w	SwapFGBG + ScaleColor + SrcCopy 				; UseStretch + 		<05JUNE92 SAH>
		dc.w	UseStretch + ColorizeInModeCase + srcBic + SwapFGBG
		dc.w	UseStretch + ColorizeInModeCase + srcXor + SwapFGBG
		dc.w	UseStretch + ColorizeInModeCase + srcOr + SwapFGBG
;
; direct src, indexed dst
;
		dc.w	ColorizeInSrcBuf + srcCopy		;
		dc.w	ColorizeInModeCase + srcOr			;
		dc.w	ColorizeInModeCase + srcXor			;
		dc.w	ColorizeInModeCase + srcBic			;
		dc.w	ColorizeInSrcBuf + SwapFGBG + srcCopy
		dc.w	ColorizeInModeCase + InvertIt + notSrcOr		;
		dc.w	ColorizeInModeCase + InvertIt + notSrcXor		;
		dc.w	ColorizeInModeCase + InvertIt + notSrcBic		;
;
; direct src, direct dst
;
		dc.w	SwapFGBG + ColorizeInModeCase + srcCopy 	; 
		dc.w	SwapFGBG + InvertIt + ColorizeInModeCase + notSrcBic		;
		dc.w	SwapFGBG + InvertIt + ColorizeInModeCase + notSrcXor		;
		dc.w	SwapFGBG + InvertIt + ColorizeInModeCase + notSrcOr		;
		dc.w	SwapFGBG + InvertIt + ColorizeInModeCase + SrcCopy  
		dc.w	SwapFGBG + ColorizeInModeCase + SrcBic		;
		dc.w	SwapFGBG + ColorizeInModeCase + srcXor		;
		dc.w	SwapFGBG + ColorizeInModeCase + srcOr		;

NOPfgColorTable
		dc.l	$FFFFFFFF		;1-bit white
		dc.l	$FFFFFFFF		;2-bit white
		dc.l	$FFFFFFFF		;4-bit white
		dc.l	$FFFFFFFF		;8-bit white
		dc.l	$7FFF7FFF		;16-bit white
		dc.l	$00FFFFFF		;32-bit white

;
; This next section of code figures out how much work we're going to have to do.
;  First we change the mode to that from the mapModeTable.
;  Next, find the correct foreground and background colors
;  Swap FG/BG colors
;  Figure out if colorizing is a NOP
;
skipTable

;
; Reintroduced code from <54> for CubeE.
;

	if CubeE then							; <56>

; <56>
; <56> d0 has table value, if pmVersion is negative, always use Stretch
; <56>
		tst.w	srcpix+pmVersion(a6)		; <56> if pmVersion negative, always use stretch
		bmi.s	@ForceStretch				; <56>
		TST.L	MASKBITS(A6)				; <56> IS THERE A MASK?
		beq.s	@DontForceStretch			; <56> Check if mask needs pmVersion
		tst.w	maskpix+pmVersion(a6)		; <56> if pmVersion negative, always use stretch
		bpl.s	@DontForceStretch			; <56> 
@ForceStretch								; <56>
		bset	#useStretchBit,d0			; <56>
@DontForceStretch							; <56>

	endif									; <56>


		btst	#5,d2						;is it a arithmetic mode?
		beq.s	@ChangeLocMode				;no, then remap mode
;
; arithmetic modes aren't colorized
;
		and.w	#~(ScaleColor+ColorizeInModeCase+ColorizeInSrcBuf),d0	;clear colorize bits
		bra.s	@ChangeLocModeDone
@ChangeLocMode
		and.b	#$f8,d2						;clear low three bits
		moveq	#3,d1
		and.b	d0,d1						;get low bits of new mode
		or.b	d1,d2						;merge with old mode
@ChangeLocModeDone
		move.w	d2,locMode(a6)				;store for modecase, BitBlt, RgnBlt

;
; if ScaleCase colorizing and src and dst bit depths are the same and source
; is black and white only (multColor bit 0) or is direct, change to ModeCase
; colorizing as an optimization.  This allows us to take BitBlt.				<05JUNE92 SAH>
;
		btst.l	#ScaleColorBit,d0			;ScaleCase colorizing?			<55>
		beq.s	@ScaleOptimizationDone		;Not scalecase, then branch		<55>
		cmp.w	#4,d3						;src direct?						<05JUNE92 SAH>
		bge.s	@checkDepth
		btst	#0,multColor+1(a6)			;src Black/White only
		beq.s	@ScaleOptimizationDone		;no, can't do anything
@checkDepth
		cmp.w	d3,d4						;src and dst same depth?		<55>
		bne.s	@ScaleOptimizationDone		;no, branch and don't change to modecase	<55>
		eor.l	#(ScaleColor+ColorizeInModeCase),d0		;clear scale color; set modecase color	<55>

@ScaleOptimizationDone
;
; Use stretch if a search proc is installed								<2May90 KON>
;
		move.l	([theGDevice]),A0			; get a pointer to the device
		tst.l	GDSearchProc(A0)			; check the head of the search chain
		beq		@CheckSwapping				; no search proc: go on
		bset.l	#UseStretchBit,d0			; force stretch

;
; if modecase colorizing, search proc is installed, and direct use unmapped fg and bg colors
;
		cmp.w	#4,d4						; destination direct?
		blt		@CheckSwapping				; nope.
		btst.l	#ColorizeInModeCaseBit,d0
		beq		@CheckSwapping				; not modecase: go on

;
; This code reintroduced from version 54 for CubeE.
;

	if CubeE then							; <56>
		move.l	([theGDevice]),a0			; <56> get a pointer to the device
		tst.l	GDSearchProc(A0)			; <56> check the head of the search chain
		beq		@CheckSwapping				; <56> no search proc: go on
	endif									; <56> 

;
; fcolor and bcolor were mapped using search proc by colormap.  We want to use
; the unmapped versions.
;
		PEA		RGBFrColor(a6)				;get fg color for colorizing
		PEA		RGBBgColor(a6)

		move.w	d0,XLateFlag(a6)			;save translation flags		<KON 5MAR91>
		_GetBackColor						;get bg color for colorizing
		_GetForeColor
		move.w	XLateFlag(a6),d0			;restore translation flags	<KON 5MAR91>

		cmp.w	#4,d4						; 16-Bit?
		beq.s	@Do16Bit					;
;
;	Convert RGB colors to 32-bit colors for foreground
;
		moveq	#0,d1
		move.b	RGBFrColor(a6),d1			;red
		swap	d1
		move.b	RGBFrColor+2(a6),d1			;green
		lsl		#8,d1
		move.b	RGBFrColor+4(a6),d1			;blue
		move.l	d1,fcolor(a6)

		moveq	#0,d1						;do background
		move.b	RGBBgColor(a6),d1			;red
		swap	d1
		move.b	RGBBgColor+2(a6),d1			;green
		lsl		#8,d1
		move.b	RGBBgColor+4(a6),d1			;blue
		move.l	d1,bcolor(a6)
		bra.s	@CheckSwapping
@Do16Bit
;
;	Convert RGB colors to 32-bit colors for background
;
		moveq	#0,d1
		move.b	RGBFrColor(a6),d1			;red
		lsl		#5,d1						;			rrrrrrrr00000
		move.b	RGBFrColor+2(a6),d1			;green		rrrrrgggggggg
		lsl.l	#5,d1						;			rrrrrgggggggg00000	<KON 5MAR91>
		move.b	RGBFrColor+4(a6),d1			;blue		rrrrrgggggbbbbbbbb
		lsr.l	#3,d1						;			000rrrrrgggggbbbbb	<KON 5MAR91>
		move.w	d1,fcolor(a6)
		move.w	d1,fcolor+2(a6)

		moveq	#0,d1
		move.b	RGBBgColor(a6),d1			;red
		lsl		#5,d1
		move.b	RGBBgColor+2(a6),d1			;green
		lsl.l	#5,d1						;			<KON 5MAR91>
		move.b	RGBBgColor+4(a6),d1			;blue
		lsr.l	#3,d1						;			<KON 5MAR91>
		move.w	d1,bcolor(a6)
		move.w	d1,bcolor+2(a6)

@CheckSwapping

		btst.l	#SwapFGBGBit,d0				;swap fg/bg colors?
		beq.s	swapdone
swapfgbk
		move.l	fcolor(a6),d1				;swap fg/bk color
		move.l	bcolor(a6),fcolor(a6)
		move.l	d1,bcolor(a6)
swapdone


;------------------------------------------------------------------------------
; Check if colorizing is a NOP.  If it is, clear the colorize bits.
;	There are three cases: ModeCase, ScaleCase, and SrcBuf colorizing
;
; SrcBuf and ScaleCase colorizing is a NOP IF
;
; for 1-bit sources:
;				 fcolor = $FFFFFFFF and bcolor = 0
;
; for deep sources:
;				 RGBFrColor = 0 and RGBBgColor = $00FFFFFF (32-bit)
;								 or RGBBgColor = $7FFF7FFF (16-bit)
;
; ModeCase colorizing is NOP if bcolor=0 and fcolor=NOPfgColorTable
;
; If ModeCase or ScaleCase colorizing, check for NOP
;
		btst.l	#ColorizeInModeCaseBit,d0
		beq		@CheckColorizeInSrcBuf		;branch if SrcBuf or ScaleCase colorizing
;
; Do ModeCase NOP check
;
		move.l	bcolor(a6),d1				;is bg color a NOP ($00000000)?
		bne		@CheckColorizeNOPDone		;bk not a NOP, go slow
		move.l	fcolor(a6),d1				;is fg color a NOP?
		lea		NOPfgColorTable,a0
		cmp.l	(a0,d4*4),d1
		bne		@CheckColorizeNOPDone		;no, it's not a NOP
;
; It's a NOP, clear colorize bits
;
		and.w	#~(ColorizeInModeCase),d0	;turn off modecase colorizing
		bra		@CheckColorizeNOPDone

@CheckColorizeInSrcBuf
;
; Check SrcBuf or ScaleCase colorizing
;
; if src is indexed and destination indexed:
;				NOP if fcolor = $FFFFFFFF and bcolor = 0
; if src is indexed and destination is direct:
;				NOP if fcolor = 0 and bcolor = $00FFFFFF (32-bit)
;									  bcolor = $7FFF7FFF (16-bit)
;
; Get fg and bg color in RGB space if colorizing at srcbuf, since our source is
; still in RGB space at that time.
;
; D3 contains src pixel depth.
; D4 contains dst pixel depth.
;
		cmp.w	#4,d3						;deep src?
		bge.s	@DeepSrc
		cmp.w	#4,d4						;dst indexed?
		bge.s	@DoDirectNOPCheck
		tst.l	bcolor(a6)					;bcolor a NOP?
		bne		@CheckColorizeNOPDone
		move.l	fcolor(a6),d1				;fcolor a NOP?
		addq.l	#1,d1
		bne		@CheckColorizeNOPDone
		bra.s	@ClearColorizeBits			;it's a NOP, clear the colorize bits
@DoDirectNOPCheck
		tst.l	fcolor(a6)
		bne		@CheckColorizeNOPDone		;fcolor not a NOP for direct device
		move.l	bcolor(a6),d1				;is fg color a NOP?
		lea		NOPfgColorTable,a0
		cmp.l	(a0,d4*4),d1
		bne		@CheckColorizeNOPDone
		bra.s	@ClearColorizeBits			;it's a NOP, clear the colorize bits
@DeepSrc

;
; if swapfgbgBit is set, we need to swap RGB fg/bg color
;
		move.w	d0,XLateFlag(a6)					;save translation flags
		btst	#swapfgbgBit,XLateFlag+1(a6)		;rgb invert?
		beq.s	@DontSwap							;don't invert

		PEA		RGBBgColor(a6)
		PEA		RGBFrColor(a6)				;get fg color for colorizing
		bra.s	@SwapDone
@DontSwap
		PEA		RGBFrColor(a6)				;get fg color for colorizing
		PEA		RGBBgColor(a6)
@SwapDone
		_GetBackColor						;get bg color for colorizing
		_GetForeColor
;
; convert 16-16-16 to 8-8-8 for 32-bit src (D3=5)
;
		cmp.w	#4,d3						;16-bit src?
		beq.s	@ConvertTo555				;yes, convert to 555

		move.l	RGBBgColor(a6),d0			;get RRRRGGGG
		lsr.l	#8,d0						;get 00RRRRGG
		lsl.w	#8,d0						;put green where it belongs, now 00RRGG00
		move.b	RGBBgColor+4(a6),d0			;get blue: 00RRGGBB
		move.l	d0,RGBBgColor(a6)

		move.l	RGBFrColor(a6),d0			;get RRRRGGGG
		lsr.l	#8,d0						;get 00RRRRGG
		lsl.w	#8,d0						;put green where it belongs, now 00RRGG00
		move.b	RGBFrColor+4(a6),d0			;get blue: 00RRGGBB
		move.l	d0,RGBFrColor(a6)

		move.w	XLateFlag(a6),d0			;get translation flags
;
; if RGBFrColor and RGBBgColor are white and black, colorizing is a nop so clear
;	ColorizeInSrcBufBit.  This is backwards from normal since it is a direct device.
;
		tst.l	RGBFrColor(a6)				;is Fr color black, ie a NOP for colorizing?
		bne.s	@CheckColorizeNOPDone		;no, colorizing is not a nop
		cmp.l	#$00FFFFFF,RGBBgColor(a6)	;is bg color white ($00FFFFFF) (a NOP)
		bne.s	@CheckColorizeNOPDone

@ClearColorizeBits
		and.w	#~(ColorizeInSrcBuf+ScaleColor),d0	;turn off SrcBuf and scale case colorizing
		bra.s	@CheckColorizeNOPDone

;
; convert 16-16-16 to 5-5-5 for 16-bit src (D3=4)
;
@ConvertTo555
		moveq	#0,d0						;clear alpha
		move.w	RGBBgColor(a6),d0			;get RRRR
		lsl.l	#5,d0						;put correct red in high word
		move.w	RGBBgColor+2(a6),d0			;get GGGG
		lsl.l	#5,d0						;put correct green in high word
		move.w	RGBBgColor+4(a6),d0			;get BBBB
		lsl.l	#5,d0						;put correct blue in high word
		swap	d0
		move.w	d0,RGBBgColor(a6)
		move.w	d0,RGBBgColor+2(a6)

		moveq	#0,d0						;clear alpha
		move.w	RGBFrColor(a6),d0			;get RRRR
		lsl.l	#5,d0						;put correct red in high word
		move.w	RGBFrColor+2(a6),d0			;get GGGG
		lsl.l	#5,d0						;put correct green in high word
		move.w	RGBFrColor+4(a6),d0			;get BBBB
		lsl.l	#5,d0						;put correct blue in high word
		swap	d0
		move.w	d0,RGBFrColor(a6)
		move.w	d0,RGBFrColor+2(a6)

;
; if RGBFrColor and RGBBgColor are white and black, colorizing is a nop so clear
;	ColorizeInSrcBufBit.  This is backwards from normal since it is a direct device.
;
		move.w	XLateFlag(a6),d0			;save translation flags
		tst.l	RGBFrColor(a6)				;is Fg color black, ie a NOP for colorizing?
		bne.s	@CheckColorizeNOPDone		;no, colorizing is not a nop
		cmp.l	#$7FFF7FFF,RGBBgColor(a6)	;is bg color white ($00FFFFFF) (a NOP)

	if CubeE or TheFuture then				; appease the assembler gods <62>
		bne.s	@CheckColorizeNOPDone
	endif									; <62>

		and.w	#~(ColorizeInSrcBuf+ScaleColor),d0	;turn off SrcBuf and scale case colorizing	

@CheckColorizeNOPDone
		move.w	d0,XLateFlag(a6)			;save translation flags
		btst	#InvertItBit,XLateFlag+1(a6)	;TEST INVERT BIT
		SNE		D7	 						;set byte flag in d7
		EXTB.L	D7							;INVERTED; D7 GETS ALL 1'S
		LEA		NOPfgColorTable,A0			;get address of white table			<42>
		AND.L	0(A0,D4.W*4),D7				;remove alpha byte/bit from mask	<42>
		MOVE.L	D7,INVERTFLAG(A6)			;SAVE INVERT FLAG
		BRA.S	NOTPAT						;=>NO, USE SOURCE INSTEAD

;------------------------------------------------------------------
;
;  PATTERN WILL BE USED.  EXPAND PATTERN TO THE CURRENT DEPTH.
;
DoPattern
		MOVEQ	#0,D7						;if mode is arithmetic, use 0 for		<SMC 18SEP90>
		BTST	#5,D2						;  the ivert flag and skip bit 2 clear	<SMC 18SEP90>
		BNE.S	@notnot						;										<SMC 18SEP90>
		BCLR	#2,D2						;TEST AND CLR INVERT BIT
		SNE		D7	 						;set byte flag in d7
		EXTB.L	D7							;INVERTED; D7 GETS ALL 1'S
@notnot	MOVE.L	D7,INVERTFLAG(A6)			;SAVE INVERT FLAG						<SMC 18SEP90>
	;	move.w	d2,locMode(a6)				;store for modecase, BitBlt, RgnBlt

		_PATEXPAND							;EXPAND PATTERN

;----------------------------------------------------
;
;  HIDE THE CURSOR IF TO THE SCREEN AND INTERSECTS MINRECT
;		(A5 must contain global ptr)
;
NOTPAT
		TST.B	CRSRFLAG(A6)					;IS DST TO A SCREEN?				<BAL 19Sep88>
		BEQ.S	NOTSCREEN						;=>NO
		PEA 	MINRECT(A6) 					;PUSH SHIELD RECT
		MOVE.L	REALBOUNDS(A6),-(SP)			;PUSH DELTA FOR GLOBAL
		_SHIELDCURSOR							;REMOVE CURSOR IF INTERSECT

NOTSCREEN
;----------------------------------------------------------------
;
;  SET UP SRC ROWBYTES, MASK ROWBYTES, AND DST ROWBYTES
;  GET SRCPIX INTO A4 AND DSTPIX INTO A5
;  GET SRCRECT INTO A2 AND DSTRECT INTO A3
;
		LEA		SRCPIX(A6),A4				;POINT TO SRCPIX
		MOVE	#nuRBMask,D0				;GET MASK FOR ROWBYTE FLAGS
		EXT.L	D0							;MAKE IT LONG
		MOVE	ROWBYTES(A4),D1 			;GET SRC ROWBYTES
		AND.L	D0,D1						;CLEAR OUT FLAG BITS
		MOVE.L	D1,SRCROW(A6)				;SRCROW := SRC ROWBYTES

@1		LEA		MASKPIX(A6),A0				;POINT TO MASKPIX
		MOVE	ROWBYTES(A0),D1 			;GET DST ROWBYTES
		AND.L	D0,D1						;CLEAR OUT FLAG BITS
		MOVE.L	D1,MASKROW(A6)				;MASKROW := MASK ROWBYTES

		LEA		DSTPIX(A6),A5				;POINT TO DSTPIX
		MOVE	ROWBYTES(A5),D1 			;GET DST ROWBYTES
		AND.L	D0,D1						;CLEAR OUT FLAG BITS
		MOVE.L	D1,DSTROW(A6)				;DSTROW := DST ROWBYTES

		MOVE.L	srcRect(a6),a2				;get srcRect 24 bit ptr @@@@ BAL 12Jan89
		MOVE.L	a2,d0						;get srcRect ptr		@@@@ BAL 09Apr88
		_rTranslate24To32
		move.l	d0,srcRect(a6)				;save 32 bit ptr		@@@@ BAL 07Jul88
		MOVE.L	dstRect(a6),a3				;get dstRect 24 bit ptr @@@@ BAL 12Jan89
		MOVE.L	a3,d0						;get dstRect ptr		@@@@ BAL 09Apr88
		_rTranslate24To32
		move.l	d0,dstRect(a6)				;save 32 bit ptr		@@@@ BAL 07Jul88

;----------------------------------------------------------------
;
; IF PATTERN MODE, GO DECIDE BETWEEN RGNBLT AND BITBLT
;
		MOVE	LOCMODE(A6),D0				;GET MODE
		ROR 	#4,D0						;IS PATTERN BIT SET ?
		BCS		NOTSTR	 					;=>YES, DON'T USE STRETCH


;----------------------------------------------------------------
;
;  CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT.
;  IF NUMER = DENOM AND SRC DEPTH = DST DEPTH THEN JUST CALL RGNBLT.
;
		MOVE	BOTTOM(A2),D1
		SUB 	TOP(A2),D1					;CALC SRC HEIGHT
		SWAP	D1							;PUT IN HI WORD
		MOVE	RIGHT(A2),D1
		SUB 	LEFT(A2),D1 				;CALC SRC WIDTH
		MOVE	D1,D0						;COPY SRC PIXCNT
		SUBQ	#1,D0						;MAKE IT 0 BASED
		MOVE	D0,SRCPIXCNT(A6)			;SAVE SRC PIXEL COUNT

		MOVE	BOTTOM(A3),D0
		SUB 	TOP(A3),D0					;CALC DST HEIGHT
		SWAP	D0							;PUT IN HI WORD
		MOVE	RIGHT(A3),D0
		SUB 	LEFT(A3),D0 				;CALC DST WIDTH

		_BlitCase							;Go determine blit style


;----------------------------------------------------------------
;
;  Determine whether to use Stretch, Scale, Rgn, or Bit Bliting
;
BlitCase
;		clr.b	FastCase(a6)				;assume not a fun case		<14SEP90 SMC>

		TST.L	MASKBITS(A6)				;*** IS THERE A MASK?
		BNE		STRETCH						;=>YES, USE STRETCH FOR NOW

		CMP.L	D0,D1						;ARE SRC AND DST THE SAME SIZE
		BNE		STRETCH						;=>NO, STRETCH THE BITS
;
; Use stretch if UseStretchBit or ColorizeInSrcBufBit is set
;
		move.w	XLateFlag(a6),d2
		and.w	#~(UseStretch+ColorizeInSrcBuf),d2				;use stretch?		<05JUNE92 SAH>
		cmp.w	XLateFlag(a6),d2
		bne		Stretch

;
; Use ScaleBlt if ScaleColorBit is set									<05JUNE92 SAH>
;
		btst	#ScaleColorBit,XlateFlag+1(a6)
		bne		xScaleBlt
		
		CMP		D3,D4						;ARE THE DEPTHS THE SAME?
		bne		xScaleBlt					;=>no, use ScaleBlt

;
; source and destination are the same depth, check if color table seeds are the same
;
		cmp		#16,dstpix+pixelType(a6)	;is it a direct device?
		beq.s	notstr						;yes, don't check seeds

		MOVE.L	SRCPIX+PMTABLE(A6),d2		;GET SRC COLOR TABLE HANDLE		<BAL>
		beq		XScaleBLT					;nil table so must remap colors	<BAL>
		move.l	d2,a0						;get handle for deref			<BAL>

		MOVE.L	(A0),A0						;POINT TO IT
		MOVE.L	CTSEED(A0),D2				;GET SEED
		MOVE.L	DSTPIX+PMTABLE(A6),A0		;GET DST COLOR TABLE HANDLE
		MOVE.L	(A0),A0						;POINT TO IT
		CMP.L	CTSEED(A0),D2				;DO THE SEEDS MATCH?
		BNE		xScaleBlt					;=>NO, use scaleBlt

NOTSTR
;----------------------------------------------------------------
;
;  NOW DECIDE BETWEEN BITBLT AND RGNBLT
;
;  ARE ALL THREE REGIONS RECTANGULAR ?   IF SO, USE BITBLT.
;
;  If the visRgn or the clipRgn is non-rectangular then call TrimRect
;  to see if the intersection of the region and MinRect is rectangular,
;  empty, or regional. 						<C951> 08Nov87 BAL
;

; <45> If going to a direct device in an arithmetic mode, force into rgnblt. Those
;	blit loops are effectively as fast as the ones in bitblt through their use of
;	runmasking.  This change allows those cases to be stripped out of bitblt.
;
		CMP		#4,D4						;direct device?
		BLT		@noforce					;no, do normal checks
		MOVE.W	locMode(A6),D0				;get penmode
		BTST	#5,D0						;arithmetic?
		BNE		XRGNBLT						;yes, force into rgnblt
@noforce

		MOVEQ	#10,D0						;GET SIZE OF RECT RGN
		MOVE.L	RGNC(A6),A0 				;GET RGNHANDLE
		MOVE.L	(A0),A0 					;DE-REFERENCE IT
		CMP 	RGNSIZE(A0),D0				;IS RGNC RECTANGULAR ?
		BNE		XRGNBLT 					;=>NO, USE RGNBLT

@chkVis	MOVE.L	RGNB(A6),A0 				;GET RGNHANDLE
		MOVE.L	(A0),A0 					;DE-REFERENCE IT
		CMP 	RGNSIZE(A0),D0 				;IS visRgn RECTANGULAR ?			<C951>
		BEQ.S	@chkClip 					;=>yes, go check clipRgn			<C951>

		MOVE.L	RGNB(A6),-(SP)				;PUSH visRgn HANDLE					<C951>
		PEA 	MINRECT(A6) 				;PUSH ADDR OF MINRECT
		MOVE.W	#-1,-(SP)					;pass Trim = True
		_TRIMRECT							;CALL TRIMRECT
		BLT 	DONE						;=>INTERSECTION EMPTY, QUIT & SHOW CURSOR
		BGT		XRGNBLT 					;=>USE RGNBLT

	; In case we fall into RgnBlt, replace visRgn with WideOpen
	; so that TrimRect doesn't get called again by seekMask.

		MOVE.L	SAVEA5(A6),A1				;Get global ptr						<BAL 26Sep88>
		MOVE.L	GRAFGLOBALS(A1),A1			;point to QD globals				<BAL 26Sep88>
		MOVE.L	WIDEOPEN(A1),RGNB(A6)		;replace visRgn with wideOpen		<BAL 26Sep88>

@chkClip
		MOVE.L	RGNA(A6),A0 				;GET RGNHANDLE
		MOVE.L	(A0),A0 					;DE-REFERENCE IT
		CMP 	RGNSIZE(A0),D0 				;IS clipRgn RECTANGULAR ?
		BEQ		XBITBLT	 					;=>YES, GO USE BITBLT

		MOVE.L	RGNA(A6),-(SP)				;PUSH clipRgn HANDLE				<C951>
		PEA 	MINRECT(A6) 				;PUSH ADDR OF MINRECT				<C951>
		MOVE.W	#-1,-(SP)					;pass Trim = True
		_TRIMRECT							;CALL TRIMRECT						<C951>
		BLT 	DONE						;=>INTERSECTION EMPTY, QUIT & SHOW CURSOR
		BEQ		XBITBLT 					;=>USE BITBLT

	; Since we will fall into RgnBlt, swap the clipRgn and the userRgn
	; so that TrimRect doesn't get called again by seekMask.

		MOVE.L	RGNA(A6),A1					;copy clipRgn						<BAL 26Sep88>
		MOVE.L	RGNC(A6),RGNA(A6)			;replace clipRgn with userRgn		<BAL 26Sep88>
		MOVE.L	A1,RGNC(A6)					;replace userRgn with clipRgn		<BAL 26Sep88>
		BRA		XRGNBLT 					;=>USE RGNBLT						<BAL 26Sep88>


XScaleBLT
;--------------------------------------------------------------
;
;  Must do depth scaling but no spatial resizing and no bit mask.
;  Only supports copy and dither modes.  No fg/bk colorizing.
;  No search procs supported for direct sources.
;
;  REGISTER USE:
;
;		A2:	SRCRECT (24 bit addr)
;		A3:	DSTRECT (24 bit addr)
;		A4: SRCPIX
;		A5: DSTPIX
;
;		D3:	SRCSHIFT
;		D4:	DSTSHIFT
;		D7: INVERT FLAG


		tst		locMode(a6)					;copy mode?
		bne		Stretch						;if not copy mode then use stretch
		
;
; Use Stretch if an alpha mode is set by looking at the streamMode				<23JUN92 SAH>
;
; Rather than looking at the stream mode directly here, we should add a call to the alpha
; routines that returns the alpha mode so that we can localize the code! Do this before it
; goes into ROM!
;
		move.l	savea5(a6),a0				;get the real a5
		move.l	GrafGlobals(a0),a0			;get the qd globals
		move.l	thePort(a0),a0				;get the port
		TST		portBits+rowBytes(A0)		;is it an old port?
		BPL		@noalpha					;yes, alpha mode is illegal
		MOVE.W	dstPix+pixelSize(A6),D2		;get depth of destination
		CMP.W	#16,D2						;direct device?
		BLT.S	@noalpha					;no, skip this stuff
		MOVE.L	grafVars(A0),D2				;get grafvars handle
		BEQ		@noalpha					;no grafvars, no alpha
		MOVE.L	D2,A0						;copy handle
		MOVE.L	(A0),A0						;dereference handle
		BTST	#PmNewGVBit-8,pmFlags(A0)	;make sure grafvars have been expanded
		BEQ.S	@noalpha					;if not, bail
		TST.B	streamMode(A0)				;is there an alpha mode
		bne		Stretch						;yes, so go slow
	
;
; now look at the actual alpha channel byte/bit to see if it contains zero. If not, we
; must go slow. This is because a streamMode of zero means that we write to both graphics
; and alpha. As an optimization, we might be able to just do this check alone for any
; streamMode so that we can go fast when writing an alpha of zero.
;
; For the purposes of Cube-E, this code is remaining as it is below, but it would be wise
; to make the tests just test memory directly to save code space!
;
		
		MOVE.W	dstPix+pixelSize(A6),D2		;get depth of destination
		cmp.w	#16,d2
		beq.s	@check16bit
	
	;dst is 32 bit
		move.l	fcolor(a6),d2
		rol.l	#8,d2						;get the alpha channel in the low byte
		tst.b	d2							;is it non-zero
		bne		Stretch						;yes, so go slow
		move.l	bcolor(a6),d2
		rol.l	#8,d2						;get the alpha channel in the low byte
		tst.b	d2							;is it non-zero
		bne		Stretch						;yes, so go slow
		bra.s	@noalpha					;ok, we can go fast!
@check16bit
	
	;dst is 16 bit
		move.l	fcolor(a6),d2
		btst	#15,d2						;is the alpha bit zero?
		bne		Stretch						;yes, so go slow
		move.l	bcolor(a6),d2
		btst	#15,d2						;is the alpha bit zero?
		bne		Stretch						;yes, so go slow
@noalpha

;
; if colorize in modecase or srcbuf flag is set, use stretch
;

		move.w	XlateFlag(a6),d2
		and.w	#~(ColorizeinSrcBuf+ColorizeInModeCase),d2
		cmp.w	XlateFlag(a6),d2
		bne.s	@toStretch					;if applying color then use stretch

		tst.w	d7							;invert the src?
		bne.s	@toStretch					;if so then use stretch
;		st		FastCase(a6)				;remember fastCase for Andy	<14SEP90 SMC>

		cmp.w	#4,d4		;dst < 16 bits/pixel?						<05JUNE92 SAH>
		blt.s	@chkSrc		;											<05JUNE92 SAH>
		cmp.w	#3,d3		;src <16 bits/pixel?
		bgt.s	@toStretch

@fast
		move.l	stNoStackPtr,goShow(a6)		;pass go home routine
		_ScaleBlt							;CALL scaleBlt
		tst		d0							;did it handle it?
		bne		DONE						;RESTORE CURSOR AND QUIT
;		
; ScaleBlt didn't handle it, so we need to make sure that if  the depths
; are one bit and ScaleColor is set, we set ColorizeInModeCase so that
; BitBlt or RgnBlt colorizes
;	

		btst	#ScaleColorBit,XlateFlag+1(a6)
		beq.s	notStr						;go ahead and use BitBlt
		eor.w	#(ScaleColor+ColorizeInModeCase),XlateFlag(a6)
		BRA.s	notStr

@chkSrc
		cmp.w	#5,d3		;src 32 bits/pixel?
		bne.s	@more						;(was Stretch)   <14SEP90 SMC>
		cmp.w	#3,d4		;dst = 8 bits/pixel?
		bne.s	Stretch
		bra.s	@fast

@more	cmp.w	#4,d3		;src 16 bits?
		beq.s	Stretch		;yes, dont do it here
		bra.s	@fast
@toStretch
		BRA.S	Stretch						;end of <14SEP90 SMC>


XBITBLT
;--------------------------------------------------------------
;
;  SINCE ALL THREE REGIONS ARE RECTANGULAR, WE WILL USE BITBLT.
;
;  REGISTER USE:
;
;		A2:	SRCRECT (32 bit addr)
;		A3:	DSTRECT (32 bit addr)
;		A4: SRCPIX
;		A5: DSTPIX
;
;		D3:	SRCSHIFT
;		D4:	DSTSHIFT
;		D7: INVERT FLAG

		moveq	#true32b,d0					;switch to 32 bit addressing
		_rSwapMMUMode			;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.b	d0,MMUsave(a6)				;save previous state for later
		move.l	srcRect(A6),a2				;reload srcRect 32 bit ptr
		move.l	dstRect(A6),a3				;reload dstRect 32 bit ptr
		_BITBLT								;CALL BITBLT
		BRA 	DONE						;RESTORE CURSOR AND QUIT


;----------------------------------------------------------------
;
; CALL RGNBLT WITH ALL SHARED LOCAL VARS SET UP AND REGS LIKE THIS:
;
;		A2:	SRCRECT (24 bit addr)
;		A3:	DSTRECT (24 bit addr)
;		A4: SRCPIX
;		A5: DSTPIX
;
;		D3:	SRCSHIFT
;		D4:	DSTSHIFT
;		D7: INVERT FLAG


XRGNBLT
		move.l	stNoStackPtr,goShow(a6)		;pass go home routine to getSeek <BAL 21Mar89>
		_StackAvail 						;GET STACK AVAIL IN D0.L
		LSR.L	#2,D0						;CONVERT BYTES TO LONGS
		SUB.L	#qdStackXtra/4,D0			;SUBTRACT SLOP FACTOR	<1.5> BAL
		MOVE.L	D0,STACKFREE(A6)			;AND SAVE FREE LONGS ON STACK
		_RGNBLT								;CALL RGNBLT
		BRA 	DONE						;RESTORE CURSOR AND QUIT

STRETCH
;
; if not shrinking and source is 1-bit b&w, clear dither flag	<24Sept90 KON>
;
		cmp.l	d0,d1						;src, dst same size?				<24Sept90 KON>
		bne.s	@dontClearDither			;branch if no						<24Sept90 KON>
		move.l	srcpix+pmtable(a6),d2		;get source color table handle		<24Sept90 KON>
		beq.s	@dontClearDither			;nil table: not 1-bit				<24Sept90 KON>
		move.l	d2,a0						;get handle for deref				<24Sept90 KON>
		move.l	(a0),a0						;point to it						<24Sept90 KON>
		moveq	#1,d2						;									<24Sept90 KON>
		cmp.l	ctseed(a0),d2				;one-bit b&w?						<24Sept90 KON>
		bne.s	@dontClearDither			;									<24Sept90 KON>
		clr.b	useDither(a6)				;don't promote source to 32-bits	<24Sept90 KON>

@dontClearDither
;----------------------------------------------------------------
;
;  (If dither flag or mask is deep) AND source is indexed data then
;  pretend the source is 32 bit/pixel RGB data and remember 
;  real depth/srcShift for later.
;
		move.w	d3,realSrcShift(a6)			;make it real anyway
		st		realDepth(a6)				;assume not promoting source to RGB
		cmp.w	#16,srcPix+pixelType(a6)	;is src direct?
		beq		@dontUseRGB					;yes, leave source depth alone
		tst.b	useDither(a6)				;is the dither bit set?
		bne.s	@UseRGB						;yes, promote source depth
		move	maskshift(a6),d2
		beq.s	@dontUseRGB

@UseRGB
		move.w	#16,srcPix+pixelType(a6)	;pretend direct data
		move.w	srcPix+pixelSize(a6),realDepth(a6)
		move.w	#32,srcPix+pixelSize(a6)	;pretend 32 bits/pixel
		moveq	#5,d3						;reset src shift
		move.w	d3,srcShift(a6)
;
; if scalecase colorizing was used, change to srcbuf colorizing since the scale table
; is not used when the src is 32-bits.  <12NOV90 KON>
;
		bclr	#ScaleColorBit,XLateFlag+1(a6)		;Colorize in scale table?
		beq.s	@NoColorizing						;no, we're cool
;
; colorizing -> change to srcbuf colorizing and setup RGBFrColor and RGBBgColor
;
		bset	#ColorizeInSrcBufBit,XLateFlag(a6)	;colorize at srcbuf time

		movem.l	A5/D0/D1,-(SP)					;Need to preserve a5, d0, and d1
		move.l	SAVEA5(A6),A5				;restore 15 for GetFore and GetBack color calls
		btst	#swapfgbgBit,XLateFlag+1(a6)		;rgb invert?
		beq.s	@DontSwap							;don't invert

		PEA		RGBBgColor(a6)
		PEA		RGBFrColor(a6)				;get fg color for colorizing
		bra.s	@SwapDone
@DontSwap
		PEA		RGBFrColor(a6)				;get fg color for colorizing
		PEA		RGBBgColor(a6)
@SwapDone
		_GetBackColor						;get bg color for colorizing
		_GetForeColor
;
; convert 16-16-16 to 8-8-8 for 32-bit src (D3=5)
;
		move.l	RGBBgColor(a6),d0			;get RRRRGGGG
		lsr.l	#8,d0						;get 00RRRRGG
		lsl.w	#8,d0						;put green where it belongs, now 00RRGG00
		move.b	RGBBgColor+4(a6),d0			;get blue: 00RRGGBB
		move.l	d0,RGBBgColor(a6)

		move.l	RGBFrColor(a6),d0			;get RRRRGGGG
		lsr.l	#8,d0						;get 00RRRRGG
		lsl.w	#8,d0						;put green where it belongs, now 00RRGG00
		move.b	RGBFrColor+4(a6),d0			;get blue: 00RRGGBB
		move.l	d0,RGBFrColor(a6)
		movem.l	(SP)+,a5/D0/D1				;Restore a5,d0, and d1

@NoColorizing
@dontUseRGB

;-----------------------------------------------------------------------
; Change source pixel size to 32 bits if deep mask and src is 16-bit
;
		cmp		#4,d3						;is it 16 bit?
		bne.s	KON
		tst.w	maskshift(a6)
		beq.s	KON
		moveq	#5,d3
KON

;----------------------------------------------------------------
;
; USE SRC AND DST SIZES TO DETERMINE STRETCHING ROUTINE
;
		MOVE.L	D0,NUMER(A6)				;NUMER := DST SIZE
		MOVE.L	D1,DENOM(A6)				;DENOM := SRC SIZE
		MOVEM.L	D3/D4,-(SP)					;SAVE D3/D4

		_SetupStretch						;CALC CASEJUMP AND HORIZ FRACT (CLOBBER D3,D4)
		MOVE.L	A0,RATIOCASE(A6)			;SAVE CASE JUMP FOR LATER
		MOVE	D0,HORIZFRACTION(A6) 		;SAVE FRACTION FOR LATER
		MOVEM.L	(SP)+,D3/D4					;RESTORE D3/D4

		clr.l	SrcPixPmTable(a6)			;									<KON 13DEC90>
		MOVE.L	SRCPIX+PMTABLE(A6),d0		;GET SRC COLOR TABLE HANDLE			<2Sep90 KON>
		beq.s	@BAL						;table not nil so continue			<2Sep90 KON>
		MOVE.L	d0,a0
		MOVE.L	(A0),d0						;POINT TO IT						<2Sep90 KON>
		_rTranslate24To32					;clean master pointer				<20AUG90 KON and BAL>
		move.l	d0,SrcPixPmTable(a6)		;									<20AUG90 KON and BAL>
@BAL

;----------------------------------------------------------------
;
;  DETERMINE AMOUNT OF STACK SPACE WE CAN USE
;  Raised amount left for interupts from 1024 to 1600 bytes			<BAL 10Apr89>
;
		_StackAvail 						;GET STACK AVAIL IN D0.L
		LSR.L	#2,D0						;CONVERT BYTES TO LONGS
		SUB.L	#qdStackXtra/4,D0			;SUBTRACT SLOP FACTOR	<1.5> BAL
		MOVE.L	D0,STACKFREE(A6)			;AND SAVE FREE LONGS ON STACK
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

;----------------------------------------------------------------
;
;  Check to see if we are shrinking 16 or 32 bit source data OR if we are
; shrinking a deep mask. If we are, allocate a buffer for the larger of the
; two. *** Currently assuming source and mask are the same size ***
;
		clr.b	useAverage(a6)				;assume not averaging
		move.w	numer+v(A6),D0				; get destination height
		move.w	denom+v(A6),D1				; get source height
		cmp.w	d1,d0						;is source larger than dest?
		bge.s	@noAvrg						;NO=> don't average

;yes, so average if 32 bit/pixel or deep mask

		cmp.w	#4,d3						;is src indexed?		<KON 2/22/90>
		blt.s	@noAvrg						;yes, skip averaging	<KON 2/22/90>
@shrink
		sge		useAverage(a6)				;always average if 16 or 32bit src		 <KON 2/22/90>
		moveq	#0,d1
		move.w	denom+h(a6),d1				;src width
		move.l	d1,d2						;make a copy src width	<16Feb90 KON and BAL>
		add.l	d2,d2						;6 bytes (R.w,G.w,B.w) per pixel	<BAL and KON 14Feb90>
		add.l	d1,d2						;d2 is byte cnt/2 of AvrgBuf		<BAL and KON 14Feb90>
;
; allocate the larger of source buffer or mask buffer
;
		cmp.w	#4,maskshift(a6)			;mask 16-bit data?
		beq.s	@DoWords					;yes, allocate twice the error buffer
;		cmp.w	#4,d3						;source 16-bit data?						<KON 2/22/90>
		cmp.w	#4,realSrcShift(a6)			;source 16-bit data (check real source)?	<KON 3/18/91>
		beq.s	@DoWords					;Twice as many pixels, allocate twice the error buffer	<KON 2/22/90>
		lsr.l	#1,d2						;both 32-bit, 1/2 as many pixels
@DoWords
		move.w	d2,ABufSize(a6)				;save long cnt for later
		SUB.L	D2,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK2
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK2

		CLR.L	-(SP)						;CLEAR ANOTHER LONG OF SLOP
@ClrBuf	CLR.L	-(SP)						;ALLOCATE AND CLEAR A LONG
		DBRA	D2,@ClrBuf					;LOOP ENTIRE BUFFER
		MOVE.L	SP,AvrgBuf(A6) 				;REMEMBER WHERE AvrgBuf IS

@noAvrg

;----------------------------------------------------------------
;
;  if dstPix is direct and we aren't averaging then no
;  reason to promote source to RGB, unless using deep mask.
;
		tst.b	realDepth(a6)				;promoting src to RGB?
		bmi.s	@LeaveItAlone				;no, all ok
		cmp.w	#16,dstPix+pixelType(a6)	;is dst direct data?
		bne.s	@LeaveItAlone				;no, we will be dithering
		tst.b	useAverage(a6)				;are we averaging
		bne.s	@LeaveItAlone				;yes, promote source
		tst.w	maskshift(a6)				;deep mask?
		bne.s	@LeaveItAlone				;yes: promote
;
;no, don't promote source
;
		move.w	realDepth(a6),srcPix+pixelSize(a6)
		move.w	realSrcShift(a6),d3			;don't fake 32-bit source
		move.w	d3,srcShift(a6)				;remember it for later
		st		realDepth(a6)				;don't expand source to 32-bit
		clr.w	SRCPIX+pixelType(A6)		;don't fake 
;
; Change colorizing back to Scalecase colorizing since the scale table
; is used for indexed sources.  <12NOV90 KON>
;
		bclr	#ColorizeInSrcBufBit,XLateFlag(a6)	;colorize at srcbuf time?
		beq.s	@NoColorizing						;no, we're cool
;
; colorizing -> change back to scalecase colorizing
;
		bset	#ScaleColorBit,XLateFlag+1(a6)		;Colorize in scale table

@NoColorizing

@LeaveItAlone

;----------------------------------------------------------------
;
; IF THE SRC AND DST ARE DIFFERENT DEPTHS, THEN MUST DO PIXEL SCALING
; IF THEY ARE THE SAME DEPTH, BUT DIFFERENT COLOR TABLES, DO PIXEL SCALING
;

		CLR.L	SCALECASE(A6)				;ASSUME NO PIXEL DEPTH SCALING
		MOVE.W	SRCPIX+pixelType(A6),D0		;IS PIXELTYPE DIRECT?			%%%
		BEQ		HasClut						;NO, IT HAS A CLUT				%%%
		cmp		#16,d0						;is it RGBDirect?
		bne		done						;unknown pixeltype -> go home

					;@@@@ should also check cmpCount, cmpSize

		MOVE.L	([theGDevice]),A2			; get the current device (trash A2)
		tst.l	gdSearchProc(A2)			; get the search proc head
		bne.s	@Slow

		cmp		d3,d4						;are the depths the same
		beq		PIXELOK						;yes, don't depth scale

;----------------------------------------------------------------
;
; The src is direct data (16 or 32 bits/pixel).
; Compute D5 as index into direct mode table based on
;
;	src16		->	add 4
;	dstIndexed	->	add 1
;	searchProc	->	add 16
;	dithering	->	add	2
;	dst16		->	add	2
;	dstAllGray	->	add 8
;
;	D3=srcShift	D4=dstShift
; 

@Slow
		moveq 	#4,d0						; init direct scaleRtn with src=16
		move.l	d0,d5
		cmp.w	d3,d5						; is src 16 bits/pixel?
		beq.s	@src16
		moveq	#0,d5						; init src to 32 bits/pixel
@src16
		cmp.w	d4,d0						; is dst 16 bits/pixel?
		bne.s	@dst32
		addq	#2,d5						; remember dst is 16 bits/pixel
@dst32

		cmp		#16,DSTPIX+pixelType(A6)	;IS PIXELTYPE DIRECT?			%%%
		beq		@noCLUT						;don't makeItable on direct device


; IF THE DST IS AN OLD GRAFPORT AND ONE BIT PER PIXEL, THEN OVERRIDE THE 
; scaleCase FOR PROPER MAPPING

		TST		d4							;ONE BIT PER PIXEL?
		BNE.S	@notBitmap					;=>NO, PROC IS OK
		MOVE.L	DSTBITS(A6),A1				;GET DST BITMAP
		TST		ROWBYTES(A1)				;IS IT OLD?
		BMI.S	@notBitmap					;=>NO, PROC IS OK
		addq	#8,d5						;force bitmap procs
		bra		@chkDither					;go check dither					<BAL 28Jan90>
@notBitmap

		addq	#1,d5						; remember dst is indexed
		MOVE.L	([GDPMap,A2]),A1			; get pixMap's handle
		MOVE.L	PMTable(A1),A0				; get the device colorTable's handle
		MOVE.L	([A0],CTSeed),D1			; get the device colorTable's ctSeed
		MOVE.L	([GDITable,A2]),A0			; get the Itable's master pointer
		CMP.L	ITabSeed(A0),D1				; has the colortable changed?
		BEQ.S	@1							; if equal, then the iTable is OK

; if table is not up to date, build a new one

		MOVE.L		PMTable(A1),-(SP)		; push theGDevice's color table handle	<BAL 26May89>
		MOVE.L		GDITable(A2),-(SP)		; push theGDevice's current iTabHandle
		MOVE.W		GDResPref(A2),-(SP)		; push the preferred iTableResolution
		_MakeITable 						; make a new table
		TST.W		QDErr					; was this sucessful?
		BEQ.S		@noErr					; nope, so quit
		ADDQ		#4,SP					; flush saved register
		BRA			doneErr					;										<BAL 26May89>
@noErr	MOVE.L		([theGDevice]),A2		; redereference in case it moved		<BAL 31Mar89>
		MOVE.L		([GDITable,A2]),A0		; get the iTable's master pointer
@1
		ADD.w	#ITTable,A0					; point directly at data
		MOVE.L	A0,stITabPtr(A6)			; save in stack frame
		SUB.w	#ITTable,A0					; get the iTable's master pointer
		MOVE.W	ITabRes(A0),stITabRes(A6)	; get the iTable resolution
		MOVE.L	([GDPMap,A2]),A1			; get pixMap's handle
		MOVE.L	([PMTable,A1]),stCLUTPtr(A6) ; get the device colorTable's ptr

		MOVE.L	gdSearchProc(A2),D0			; get the search proc head
		bne.s	@search						; go use search routines


;	Here we know that the dst is indexed and no search proc is present,
;	so determine if the dst clut is all grays and/or we are dithering.

;	the iTable's master pointer is in A0

		MOVEQ	#1,D0						; prime the register again
		MOVE	ITabRes(A0),D2				; get the inverse table resolution (and Bit-field width)
		LSL.L	D2,D0						; calculate 2^^res
		LSL.L	D2,D0						; square it
		LSL.L	D2,D0						; cube it
		LEA		ITTable(A0,D0.L),A1			; point us at the ITabInfo
		tst.w	iTabFlags(a1)				; is this a grayITab?
		bpl.s	@chkDither					; no, go see if dithering
		add.w	#ITabInfo,a1				; point past header
		move.l	a1,stITabInfo(a6)			; save for later
		addq	#8,d5						; remember to use gray routines

		moveq	#40,d0
		cmp.l	ITabSeed(a0),d0				; is dst the standard 8-bit gray clut?
		beq.s	@readyProc					; yes, ignore dithering for speeed!

@chkDither

		tst.b	useDither(a6)				; should we dither?
		beq.s	@readyProc					; no, we're set
		addq	#2,d5						; remember to use dither routines

;
;	Compute and allocate scanline buffer for dither error from previous scan	<BAL 29Aug88>
;

		MOVEQ	#0,D0						;CLEAR HIGH WORD OF D0
		MOVE	NUMER+H(A6),D0				;GET WIDTH OF DST
		lsl.l	d4,d0						;get bit width
		add.l	#31,d0						;round to long boundary
		lsr.l	d4,d0						;get adjusted pixel width
		btst	#3,d5						;is dst a grayscale clut?
		bne.s	@gray						;only need 2 bytes per pixel for gray error <BAL 18Mar89>

		move.l	d0,d1						;make a copy						<BAL and KON 14Feb90>
		ADD.l	D0,D0						;6 bytes (R.w,G.w,B.w) per pixel	<BAL and KON 14Feb90>
		add.l	d1,d0						;d0 is byte cnt/2 of ErrBuf			<BAL and KON 14Feb90>
@gray	LSR.l 	#1,D0						;AND DIV BY 2 FOR LONGS				<BAL and KON 14Feb90>

		SUB.L	D0,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK3
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK3

		CLR.L	-(SP)						;CLEAR ANOTHER LONG OF SLOP
@ClearB	CLR.L	-(SP)						;ALLOCATE AND CLEAR A LONG
		DBRA	D0,@ClearB					;LOOP ENTIRE BUFFER
		MOVE.L	SP,ErrBUF(A6) 				;REMEMBER WHERE ErrBuf IS
		clr.b	ErrDir(a6)					;init to carry error to right
		BRA.S	@readyProc					; and continue


;	Here we know that the dst is direct so check if search proc is present.


@noCLUT
		MOVE.L	gdSearchProc(A2),D0			; get the search proc head
		beq.s	@readyProc
@search
		MOVE.L	D0,stSProc(A6)				; put search procs list head in stack frame
		bset	#4,d5						; use search routines


;	We 	have the scaleCase routine selector in D5 so compute address
;	of routine and stuff it in scaleCase for later


@readyProc
		move.w	d5,d0						;copy selector
		lsr.w	#3,d0						;determine table to use
		lea 	(stColorTabPtr,ZA0,d0*4),A0	;POINT TO MODE TABLE
		move.l	(a0),a0						;get table
		and.w	#7,d5						;get position in this table
		add.l	0(A0,D5*4),A0				;GET CASE JUMP ADDRESS
		MOVE.L	A0,scaleCase(A6)			; put depth scaling routine in stack frame
		BRA		PIXELOK						;=>ALREADY GOT ROUTINE

Bogus	;_debugger
		bra		Done


	ALIGN 	4


				;Color Blits
stColorTab
		DC.L	Bogus-stColorTab				;0		32	to	32
		DC.L	Scale32toIndexed-stColorTab		;1		32	to	Indexed
		DC.L	Scale32to16-stColorTab			;2		32	to	16
		DC.L	Dither32toIndexed-stColorTab	;3		32	to	Indexed Dither
		DC.L	Scale16to32-stColorTab			;4		16	to	32
		DC.L	Scale16toIndexed-stColorTab		;5		16	to	Indexed
		DC.L	Bogus-stColorTab				;6		16	to	16
		DC.L	Dither16toIndexed-stColorTab	;7		16	to	Indexed Dither


				;Gray Blits
stGrayTab
		DC.L	Scale32toBitmap-stGrayTab		;8		32	to	BitMap
		DC.L	Scale32toGray-stGrayTab			;9		32	to	Indexed
		DC.L	Dither32toBitmap-stGrayTab		;A		32	to	(16) ->BitMap Dither	<BAL 28Jan90>
		DC.L	Dither32toGray-stGrayTab		;B		32	to	Indexed Dither
		DC.L	Scale16ToBitMap-stGrayTab		;C		16	to	BitMap
		DC.L	Scale16toGray-stGrayTab			;D		16	to	Indexed
		DC.L	Dither16toBitmap-stGrayTab		;E		16	to	(16) ->BitMap Dither	<BAL 28Jan90>
		DC.L	Dither16toGray-stGrayTab		;F		16	to	Indexed Dither


				;Search Blits
stSearchTab
		DC.L	Search32to32-stSearchTab		;10		32	to	32						<20AUG90 KON>
		DC.L	Search32toIndexed-stSearchTab	;11		32	to	Indexed
		DC.L	Search32to16-stSearchTab		;12		32	to	16
		DC.L	Bogus-stSearchTab				;13		32	to	Indexed Dither
		DC.L	Search16to32-stSearchTab		;14		16	to	32
		DC.L	Search16toIndexed-stSearchTab	;15		16	to	Indexed
		DC.L	Search16to16-stSearchTab		;16		16	to	16						<20AUG90 KON>
		DC.L	Bogus-stSearchTab				;17		16	to	Indexed Dither


;----------------------------------------------------------------
;
; The src is indexed data (1,2,4,8 bits/pixel).
; If seeds don't match or depths are different then make a scale table.
; Special case 1-bit source.
;

HasClut
		MOVE.L	SRCPIX+PMTABLE(A6),d0		;GET SRC COLOR TABLE HANDLE		<BAL>
		beq.s	DOXLATE						;table not nil so continue		<BAL>
		move.l	d0,a0						;get handle for deref			<BAL>
		move.l	(a0),a0						;point to it					<KON>
		MOVE.L	CTSEED(A0),D0				;GET SEED

		MOVE.L	DSTPIX+PMTABLE(A6),A0		;GET DST COLOR TABLE HANDLE
		cmp		#16,DstPix+pixelType(a6)	;is it a direct device?
		beq.s	@chk1						;yes, don't check seeds
		MOVE.L	(A0),A0						;POINT TO IT
		CMP.L	CTSEED(A0),D0				;DO THE SEEDS MATCH?
		BNE.S	@chk1						;=>NO, MUST TRANSLATE


		CMP		D3,D4						;DOES SRC DEPTH = DST DEPTH?
		bne.s	@chk1						;no, then scale pixels
;
; check fg and bk color and if they aren't black and white
; then take chk1 case, otherwise, take pixelok case.
;
; <KON 5MAR91> begins here... This fixes a problem with drawing to bitmaps.  The problem
; is when the main device is direct and the app sets the fg color to black and the
; bg color to white, we think we are colorizing since the sense of what is black and
; what is white is reversed.  This can only happen when the destination pixmap is
; 1-bit and the destination GDevice is a direct device.  Thus, I special case this
; situation and check the fg and bg colors for black and white correctly.  There is 
; probably a more elegant fix for this, but with 7.0 ready to ship this implementation
; causes the least risk since it should effect only the case we are interested in.  If
; it's not this particular case, we branch to @OldWay and processing continues as before.
; YUK!
;
;Êfrom QDciPatchROM.a verbatim (down through the RTD)							<sm 6/9/92>stb
;
; if destination device is direct, and dst pixmap 1-bit bcolor = FFFFFFFF and 
; fcolor = 0 is NOP
; else, bcolor = 0, fcolor = $FFFFFFFF is NOP
;
		cmp		#1,d3						;1-bit?
		bne.s	@OldWay						;no, do it as before
		MOVE.L	([theGDevice]),A2			; get the current device
		MOVE.L	([GDPMap,A2]),A1			; get pixMap
		cmp		#16,pixelType(A1)			; is dest. GDevice direct?
		bne.s	@OldWay					;
;
; Destination pixmap is indexed but GDevice is direct.  Assume we are going to
; an old 1-bit port.
;
		move.l	fcolor(a6),d1
		bne.s	@chk1						;fg not black, go slow
		move.l	bcolor(a6),d1
		addq	#1,d1
		beq		PIXELOK						;bk white, fg black, go fast
		bra.s	@chk1

; <KON 5MAR91> ends here...
@OldWay
		move.l	bcolor(a6),d1
		bne.s	@chk1						;fg not black, go slow
		move.l	fcolor(a6),d1
		addq	#1,d1
		beq		PIXELOK						;bk white, fg black, go fast

@chk1	TST		D3							;IS SRC ONE BIT PER PIXEL?
		BNE.S	DOXLATE						;=>NO, Build mapping table
		MOVEQ	#1,D1						;GET CTSEED FOR DEFAULT ONE BIT TABLE
		CMP.L	D0,D1						;IS IT THE DEFAULT?
		BEQ		SRCONE						;=>YES, USE EXPAND TABLES FOR SPEED

DOXLATE	MOVE	SRCPIX+PIXELSIZE(A6),D1		;GET SRC BITS PER PIXEL
		MOVEQ	#1,D0						;# ENTRIES = 2^ PIXELSIZE
		LSL		D1,D0						;CALC # ENTRIES
		SUB.L	D0,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

; IF THE DST IS AN OLD GRAFPORT AND IS ONE BIT PER PIXEL, THEN OVERRIDE THE 
; SEARCH PROC FOR PROPER MAPPING

		MOVEQ	#0,D7						;ASSUME NO PROC INSTALLED
		CMP		#1,DSTPIX+PIXELSIZE(A6)		;ONE BIT PER PIXEL?
		BNE.S	@PROCOK						;=>NO, PROC IS OK
		MOVE.L	DSTBITS(A6),A1				;GET DST BITMAP
		TST		ROWBYTES(A1)				;IS IT OLD?
		BMI.S	@PROCOK						;=>NO, PROC IS OK

		MOVEQ	#1,D7						;FLAG PROC INSTALLED
		PEA		ONEBITPROC					;POINT TO OUR PROC
		_ADDSEARCH							;AND INSTALL IT

@PROCOK	MOVE.L	SAVEA5(A6),A5				;GET A5 FOR MAKESCALETBL
		MOVE.L	A4,-(SP)					;PUSH SRCPIX POINTER

;
; If bit 0 = 1, then MakeScaleTbl colorizes, otherwise it don't.
;  if mode is BIC or OR, then don't colorize in MakeScaleTbl
;
		MOVE.w	XLateFlag(a6),-(SP)			;pass arithmetic mode to get fg/bg relative colors
		_MakeScaleTbl						;AND MAKE PIXEL TRANSLATION TABLE

;------------------------------------------------------------------------------------------
;
; <C947> 08Nov87 BAL  begins here:
;
;------------------------------------------------------------------------------------------
;
;		MakeScaleTbl is called whenever the src and dst pixmaps have different
;		pixel depths or different color table seeds.  MakeScaleTbl returns a
;		pixel translation table used to map each src pixel to a dst pixel.
;
;		Here I check to see if the translation table returned by MakeScaleTbl is in
;		actuality an identity mapping--in which case no mapping at all is required!
;		In order for an identity mapping to result the src and dst pixMaps must be of the same
;		depth.
;
;		If an identity mapping is detected, I must decide whether a stretch blit loop is
;		really required (ie src rect ­ dst rect or maskBits ­ nil) or whether a much faster
;		region blit or bit blit loop would suffice.
;
;------------------------------------------------------------------------------------------

		move	SRCPIX+PIXELSIZE(A6),d1		;get src bits/pixel
		cmp		DSTPIX+PIXELSIZE(A6),d1		;is it the same as dst bits/pixel?
		bne.s	@ScaleOK					;no, have to do pixel scaling

											;inspect scale table for equality
@chkTbl	MOVEQ	#1,D0						;# ENTRIES = 2^ PIXELSIZE
		LSL		D1,D0						;CALC # ENTRIES in d0
		move	d0,d1						;make a copy of long count
		lsl		#2,d1						;get size of table
		subq	#1,d0						;make counter zero based for dbra
		move.l	sp,a0						;point to scale tbl
		add		d1,a0						;point past end of table

@1		cmp.l	-(a0),d0					;compare with dst pixel value
		dbne	d0,@1
		bne.s	@ScaleOK					;tables are not equal so perform pixel scaling

		CLR.L	ScaleCase(a6)				;remember no pixel xlation needed	 <BAL 09Apr90>
		MOVE.L	SP,ScaleTbl(A6)				;SAVE TRANSLATION TABLE just in case <BAL 09Apr90>

;if we installed a proc get rid of it before short circuiting stretch

		TST		D7							;DID WE INSTALL A PROC
		BEQ.S	@NOPRC						;=>NO, DON'T NEED TO REMOVE
		PEA		ONEBITPROC					;ELSE PUSH OUR PROC
		_DELSEARCH							;AND DELETE IT

@NOPRC	LEA		DSTPIX(A6),A5				;RESTORE DSTPIX POINTER
		TST.L	MASKBITS(A6)				;*** IS THERE A MASK?
		BNE		PIXELOK						;=>YES, USE STRETCH BUT DON'T PIXEL TRANSLATE

;----------------------------------------------------------------
;
;  CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT.
;  IF NUMER = DENOM AND SRC DEPTH = DST DEPTH THEN JUST CALL RGNBLT.
;
		MOVE.L	NUMER(A6),D0				;GET WIDTH,HEIGHT OF DST
		CMP.L	DENOM(A6),D0				;SAME AS WIDTH,HEIGHT OF SRC?
		BNE		PIXELOK						;no, must call stretch
		MOVE.L	INVERTFLAG(A6),D7			;restore invert flag			<<C983>>
		BRA		NOTSTR						;jump back and decide between bitblt and rgnblt
											;don't really have to use stretch at all!

;------------------------------------------------------------------------------------------
;
; <C947> 08Nov87 BAL  ends here.
;
;------------------------------------------------------------------------------------------
@ScaleOK
		MOVE.L	SP,ScaleTbl(A6)				;SAVE POINTER TO TRANSLATION TABLE
		LEA		DSTPIX(A6),A5				;RESTORE DSTPIX POINTER

		TST		D7							;DID WE INSTALL A PROC
		BEQ.S	@NOPROC						;=>NO, DON'T NEED TO REMOVE
		PEA		ONEBITPROC					;ELSE PUSH OUR PROC
		_DELSEARCH							;AND DELETE IT

@NOPROC	move.l	stIndexedSrc,A0				;POINT TO THE SCALING ROUTINE
		MOVE.L	A0,SCALECASE(A6)			;AND SAVE CASE JUMP FOR LATER
		BRA		PIXELOK						;=>ALREADY GOT ROUTINE


	ALIGN 	Alignment

ONEBITPROC
;----------------------------------------------------------------
;  FUNCTION ONEBITPROC(MYCOLOR:RGBCOLOR; VAR INDEX: LONG): BOOLEAN;
;
;  THIS IS A COLOR MANAGER CUSTOM SEARCH PROC THAT MAPS RGB TO
;  BLACK AND WHITE FOR MAPPING TO OLD GRAFPORTS.
;  Algorithm modified to use [5 9 2] luminance mapping.  <BAL 30Mar89>
;
MYINDEX	EQU		4
MYRGB	EQU		8
RESULT	EQU		12

		ST.B	RESULT(SP)					;ALWAYS RETURN TRUE
		MOVE.L	MYRGB(SP),A0				;POINT TO RGB
		moveq	#0,d0						;clear out high end
		moveq	#0,d1						;clear out high end
		move.w	red(a0),d0					;get red
		move.l	d0,a1						;keep red in a1
		move.w	green(a0),d1				;get green
		add.l	d0,d1						;accumulate luminance in d1
		move	blue(a0),d0
		add.l	d0,d1						;accumulate luminance in d1
		add.l	d0,d1						;accumulate luminance in d1
		lsr.l	#2,d1
		add.l	a1,d1						;accumulate luminance in d1
		move	green(a0),d0
		add.l	d0,d1						;accumulate luminance in d1
		add.l	d0,d1						;accumulate luminance in d1
		lsr.l	#2,d1
		MOVE.L	MYINDEX(SP),A1				;POINT TO INDEX
		CLR.L	(A1)						;ASSUME INDEX = WHITE
		tst		d1							;check luminance
		BMI.S	@RESOK						;=>IF >= $8000 THEN WHITE
		ADDQ.L	#1,(A1)						;ELSE RETURN BLACK
@RESOK	RTD		#8							;STRIP PARAMS AND RETURN


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb
;----------------------------------------------------------------
;
; FOR 1 BIT TO N BIT PIXEL-STRETCHING, SET UP EXPAND ROUTINE.
; 

SRCONE	move.l	ExTblPtr,A0					;POINT TO ROUTINE TABLE
		CMP.W	#4,D4						;are we going to a direct device?		<42>
		BLT.S	@2							;no, take normal path					<42>
		MOVE.W	locMode(A6),D0				;get transfer mode						<42>
		BTST	#5,D0						;arithmetic?							<42>
		BNE.S	@2							;yes, take normal path					<42>
		AND.W	#3,D0						;is the mode copy?						<42>
		BEQ.S	@2							;yes, take normal path (colors swapped)	<42>
		MOVE.L	alphaMask(A6),D1			;get the alpha mask						<42>
		TST.L	INVERTFLAG(A6)				;are we inverting?						<42>
		BEQ.S	@1							;no, leave invertflag alone				<42>
		MOVE.L	D1,INVERTFLAG(A6)			;yes, change invertflag to alphamask	<42>
	@1:	CLR.L	alphaFore(A6)				;foreground is zeroes					<42>
		MOVE.L	D1,alphaBack(A6)			;background is alphamask				<42>
		ADD.L	40(A0,D4*4),A0				;get address of special expansion loop	<42>
		BRA.S	@gotScale					;jump to common code					<42>
	@2:										;take normal path						<42>
;
;take special loops if colorizing
;
		btst	#ScaleColorBit,XLateFlag+1(a6)		;colorize in expansion?
		beq.s	@nocolorize							;no, colorize in blit loop
@colorize
		add.l	32(A0,d4*4),a0						;colorize in expansion
	if 0 then										;why?					<10Sept90 KON>
;
; if swapfgbgBit is set, we need to swap fg/bg color again
;
		btst	#swapfgbgBit,XLateFlag+1(a6)		;rgb invert?
		beq.s	@gotScale							;don't invert
		move.l	fcolor(a6),d1						;swap fg/bk color
		move.l	bcolor(a6),fcolor(a6)
		move.l	d1,bcolor(a6)
	endif
		bra.s	@gotScale

@nocolorize
		cmp.w	#4,d4
		blt.s	@indexedDst
		add.l	8(A0,D4*4),A0				;choose between direct loops
		bra.s	@gotScale
@indexedDst
		add.l	0(A0,D4*4),A0				;USE DSTSHIFT TO SELECT ROUTINE
@gotScale
		MOVE.L	A0,SCALECASE(A6)			;SAVE CASE JUMP FOR LATER

;-----------------------------------------------------------------------
;
;  We've got our ScaleCase.
;
PIXELOK

;-----------------------------------------------------------------------
;
;  ALLOCATE AND CLEAR SRCBUF TO HOLD SRCWIDTH.
;
		MOVEQ	#0,D0						;CLEAR HIGH WORD OF D0
		MOVE	DENOM+H(A6),D0				;GET WIDTH OF SRC
		LSL.l	D3,D0						;SCALE WIDTH BY SRC DEPTH
		SUBq.l 	#1,D0						;SUBTRACT 1 BIT
		LSR.l 	#5,D0						;AND DIV BY 32 FOR LONGS
		MOVE	D0,SRCLONGS(A6) 			;SAVE FOR LATER

		SUB.L	D0,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

		CLR.L	-(SP)						;CLEAR A LONG OF SLOP AT RIGHT
CLRSRC	CLR.L	-(SP)						;ALLOCATE AND CLEAR A LONG
		DBRA	D0,CLRSRC					;LOOP ENTIRE BUFFER
		MOVE.L	SP,SRCBUF(A6)				;REMEMBER WHERE SRCBUF IS
		MOVE.L	SP,DSTBUF(A6) 				;ASSUME NO HORIZONTAL STRETCHING
		MOVE.L	SP,SCALEBUF(A6)				;ASSUME NO PIXEL TRANSLATION


;-----------------------------------------------------------------------
;
;  ALLOCATE AND CLEAR DSTBUF TO HOLD DSTLONGS.
;
		MOVEQ	#0,D0						;CLEAR HIGH WORD OF D0
		MOVE	NUMER+H(A6),D0				;GET WIDTH OF DST
		CMP		DENOM+H(A6),D0				;SAME AS WIDTH OF SRC?
		BEQ.S	NOHSTRETCH					;=>YES, NO HORIZONTAL STRETCHING

		LSL.l	D3,D0						;SCALE WIDTH BY SRC DEPTH

		SUBq.l 	#1,D0						;SUBTRACT 1 BIT
		LSR.l 	#5,D0						;AND DIV BY 32 FOR LONGS
		MOVE	D0,DSTLONGS(A6) 			;SAVE FOR LATER

		SUB.L	D0,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

		CLR.L	-(SP)						;CLEAR ANOTHER LONG OF SLOP
CLRDST	CLR.L	-(SP)						;ALLOCATE AND CLEAR A LONG
		DBRA	D0,CLRDST					;LOOP ENTIRE BUFFER
		MOVE.L	SP,DSTBUF(A6) 				;REMEMBER WHERE DSTBUF IS
		MOVE.L	SP,SCALEBUF(A6)				;DEFAULT SCALEBUF = DSTBUF


NOHSTRETCH
;-----------------------------------------------------------------------
;
;  ALLOCATE AND CLEAR MASK TO HOLD srcMASKlongs.
;
		CLR.L	MASKNUMER(A6)				;SRC MASK WIDTH
		CLR.L	MASKDENOM(A6)				;  = DST MASK WIDTH
		MOVE.L	MASKBITS(A6),D0				;IS THERE A MASK?
		BEQ		NODST						;=>NO, DON'T ALLOCATE MASK BUFFERS

;----------------------------------------------------------------
;
;  CALC NUMER AND DENOM BASED ON DSTRECT AND MASKRECT.
;
		MOVE.L	MASKRECT(A6),A0				;POINT TO MASKRECT
		MOVE	BOTTOM(A0),D1
		SUB 	TOP(A0),D1					;CALC MASK HEIGHT
		SWAP	D1							;PUT IN HI WORD
		MOVE	RIGHT(A0),D1
		SUB 	LEFT(A0),D1 				;CALC MASK WIDTH

		MOVE	BOTTOM(A3),D0
		SUB 	TOP(A3),D0					;CALC DST HEIGHT
		SWAP	D0							;PUT IN HI WORD
		MOVE	RIGHT(A3),D0
		SUB 	LEFT(A3),D0 				;CALC DST WIDTH

;----------------------------------------------------------------
;
; USE MASK AND DST SIZES TO DETERMINE MASK STRETCHING ROUTINE
;
		MOVEM.L	D3/D4,-(SP)					;SAVE D3/D4
		MOVE.L	D0,MASKNUMER(A6)			;NUMER := DST SIZE
		MOVE.L	D1,MASKDENOM(A6)			;DENOM := SRC SIZE
		_SetupStretch						;CALC CASEJUMP AND HORIZ FRACT (CLOBBER D3,D4)
		MOVE.L	A0,MASKCASE(A6)				;SAVE CASE JUMP FOR LATER
		MOVE	D0,MASKFRACT(A6) 			;SAVE FRACTION FOR LATER
		MOVEM.L	(SP)+,D3/D4					;RESTORE D3/D4
		MOVEQ	#0,D2						;CLEAR HIGH WORD OF D0
		move.w	MASKDENOM+H(A6),d2			;get width of mask
;
;unless depth = 1, depth promoted to 32 bit/pix
;
		move.w	maskshift(a6),d1
		beq.s	@onebitmask

		move.l	maskpix+pmTable(a6),a0
		move.l	(a0),d0						;get pointer to color table			<20AUG90 KON and BAL>
		_rTranslate24To32					;clean master pointer				<20AUG90 KON and BAL>
		move.l	d0,MaskPixPmTable(a6)		;									<20AUG90 KON and BAL>

		moveq	#5,d1
		lsl.l	d1,d2						;scale width by mask depth
@onebitmask
		SUB.l 	#1,D2						;SUBTRACT 1 BIT
		LSR.l 	#5,D2						;AND DIV BY 32 FOR LONGS
		MOVE	D2,SRCMASKLONGS(A6) 		;SAVE FOR LATER

		SUB.L	D2,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

		CLR.L	-(SP)						;CLEAR A LONG OF SLOP AT RIGHT
CLRMSK1	CLR.L	-(SP)						;ALLOCATE AND CLEAR A LONG
		DBRA	D2,CLRMSK1					;LOOP ENTIRE BUFFER
		MOVE.L	SP,SRCMASKBUF(A6)			;REMEMBER WHERE SRCMASKBUF IS


;-----------------------------------------------------------------------
;
;  ALLOCATE AND CLEAR DSTMASKBUF TO HOLD MASKLONGS.
;
		MOVE.L	SP,DSTMASKBUF(A6)			;ASSUME NO DSTBUF
		MOVEQ	#0,D0						;CLEAR HIGH WORD OF D0
		MOVE	MASKNUMER+H(A6),D0			;GET WIDTH OF DST
		CMP		MASKDENOM+H(A6),D0			;SAME AS WIDTH OF SRC?
		BEQ.S	NODST						;=>YES, NO DSTMASKBUF
											;mask depth in d1 from above
		lsl.l	d1,d0						;scale width by mask depth
@onebitmask
		SUB.l 	#1,D0						;SUBTRACT 1 BIT
		LSR.l 	#5,D0						;AND DIV BY 32 FOR LONGS
		MOVE	D0,DSTMASKLONGS(A6) 		;SAVE FOR LATER

		SUB.L	D0,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

		CLR.L	-(SP)						;CLEAR A LONG OF SLOP AT RIGHT
CLRMSK2	CLR.L	-(SP)						;ALLOCATE AND CLEAR A LONG
		DBRA	D0,CLRMSK2					;LOOP ENTIRE BUFFER
		MOVE.L	SP,DSTMASKBUF(A6) 			;REMEMBER WHERE DSTMASKBUF IS


;-----------------------------------------------------------------------
;
;  ALLOCATE AND CLEAR SCALEBUF TO HOLD SCALELONGS.
;
NODST	TST.L	SCALECASE(A6)				;IS THERE A SCALE ROUTINE?
		BEQ.S	NOSCALE						;=>NO, DON'T ALLOCATE BUFFER

DOSCALE	MOVEQ	#0,D0						;CLEAR HIGH WORD OF D0
		MOVE	NUMER+H(A6),D0				;GET DST WIDTH
		SUB.l 	#1,D0						;SUBTRACT 1 BIT				@@@@ altered to use longs 03May88 BAL
		LSL.l	D4,D0						;SCALE DSTBUF BY DSTSHIFT	@@@@ altered to use longs 03May88 BAL
		LSR.l 	#5,D0						;AND DIV BY 32 FOR LONGS	@@@@ altered to use longs 03May88 BAL
		MOVE	D0,SCALELONGS(A6)

		SUB.L	D0,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

		CLR.L	-(SP)						;CLEAR A LONG OF SLOP AT RIGHT
		CLR.L	-(SP)						;CLEAR ANOTHER LONG OF SLOP
CLRCHNK	CLR.L	-(SP)						;ALLOCATE AND CLEAR A LONG
		DBRA	D0,CLRCHNK					;LOOP ENTIRE BUFFER
		MOVE.L	SP,SCALEBUF(A6) 			;REMEMBER WHERE SCALEBUF IS


;_________________________________________________________________________________________
;
;  CALC expansion buffer  = [ (minRect.right-minRect.left) div 32 + 1 ] * pixelsize - 0
;  CALC bufSize  = [ (minRect.right-minRect.left)  * pixelsize - 1 ] div 32	+ 1		<C954> 08Nov87 BAL
;
NOSCALE	MOVE.L	DSTRECT(A6),A0				;POINT TO DSTRECT
		MOVE	LEFT(A0),D1 				;GET DSTRECT LEFT
		SUB 	BOUNDS+LEFT(A5),D1			;CONVERT TO GLOBAL COORDS
		LSL.L	D4,D1						;CONVERT DST PIXELS TO BITS
		AND		#$FFE0,D1					;TRUNC TO MULT OF 32
		ASR.L	D4,D1						;CONVERT DST BITS TO PIXELS
		ADD 	BOUNDS+LEFT(A5),D1			;CONVERT BACK TO LOCAL
		MOVE	D1,BUFLEFT(A6)				;SAVE AS BUFLEFT
		MOVEQ	#0,D0						;CLEAR HIGH WORD OF D0
		MOVE	MINRECT+RIGHT(A6),D0		;GET MINRECT RIGHT
		SUB 	D1,D0						;CALC WIDTH IN DOTS
		MOVE	D0,bufSize(A6)				;for arithmetic modes, prime bufSize with dot size
		move	d0,d1						;save for expansion scanline buffer	<C954>

		ext.l	d1							;clear out high word				<C954>
		lsl.l	d4,d1						;convert to bits					<C954>
		subq.l	#1,d1						;force downward round				<C954>
		LSR.l	#5,D1						;GET NUMBER OF LONGS IN SCANBUF - 1	<C954>
		addq.l	#1,d1						;***make it one based for stretch!!	<C954>
		BTST	#5,locMode+1(A6)			;arithmetic?
		BNE.S	@skipDotToLong				;if so, donÕt update bufSize

		MOVE	D1,BUFSIZE(A6)				;BUFSIZE = # LONGS -1				<C954>

@skipDotToLong
		LSR		#5,D0						;GET NUMBER OF LONGS IN SCANBUF
		ADDQ	#1,D0						;MAKE IT ONE BASED
		LSL		D4,D0						;MULTIPLY BY DST PIXEL DEPTH
											;*** Leave it one based !!!?
		SUB.L	D0,STACKFREE(A6)			;IS THERE ENOUGH STACK?
		bpl.s	@stkOK
		_stNoStack							;=>NOT ENOUGH STACK, QUIT
@stkOK

;-----------------------------------------------------------------------
;
;  ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK.
;
		CLR.L	-(SP)						;TWO FOR SLOP
		CLR.L	-(SP)						;ONE FOR SLOP
CLRMASK CLR.L	-(SP)						;ALLOCATE AND CLEAR
		DBRA	D0,CLRMASK					;LOOP TILL DONE
		MOVE.L	SP,RGNBUFFER(A6) 			;REMEMBER WHERE RGNBUFFER IS


;--------------------------------------------------------------------
;
;  ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
;  GET SEEK ROUTINE INTO SEEKMASK(A6)
;  GET EXPAND ROUTINE INTO EXRTN(A6) FOR SEEK ROUTINE
;  Clobbers: A0-A3, D0-D6
;
		move.l	stNoStackPtr,goShow(a6)		;pass go home routine to getSeek <BAL 21Mar89>
		clr.l	runBuf(a6)					;don't use run clipping		<1.5> BAL

		move.l	dstmaskbuf(a6),d7			;save dstmaskbuf
		tst.w	maskshift(a6)				;deep mask?
		beq.s	@dontTrickGetSeek			;branch if no
		clr.l	dstmaskbuf(a6)				;make seek think there is no mask
@dontTrickGetSeek
		MOVE.L	RGNC(A6),-(SP)				;PUSH USER RGNHANDLE (never TrimRect'ed)
		MOVE.L	RGNB(A6),-(SP)				;PUSH VIS RGNHANDLE
		MOVE.L	RGNA(A6),-(SP)				;PUSH CLIP RGNHANDLE
		MOVE.L	#2,-(SP)					;PUSH HANDLE COUNT - 1
		_GETSEEK							;GET EXPAND ROUTINE INTO EXRTN(A6)
											;AND SEEK ROUTINE INTO SEEKMASK(A6)
		move.l	d7,dstmaskbuf(a6)			;restore
;--------------------------------------------------
;
;  CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES
;  GET INVERTFLAG INTO D7
;
SETMODE MOVE	LOCMODE(A6),D0				;GET THE MODE
		BTST	#5,D0						;arithmetic mode?
		BEQ.S	@notArithMode
		CMP		#$40,D0						;source modes are $20 É $27, $32
		BGT		DONE						;if bigger, undefined
		BTST	#3,D0						;pattern?
		BNE		DONE
		AND		#$17,D0						;consider only 8 mode variants
		BCLR	#4,D0						;clear hilite bit
		BEQ.S	@notHilite
		SUBQ	#2,D0						;hilite?
		BNE		DONE
		ADDQ	#8,D0						;advance to hilite ($0C - 4)
@notHilite
		cmp		#16,dstPix+pixelSize(A6) 	;dst 32 bits/pixel?
		bge.s	@useLoops16					;yes, use alternate table
		ADDQ	#4,D0						;advance past normal src modes
		BRA.S	@setupJump

@useLoops16
		bne.s	@useLoops32					;yes, use alternate table
		move.l 	stArith16TabPtr,A0			;POINT TO 16 bit MODE TABLE
@getMode
		BCLR	#4,D0						;clear hilite bit
		add.l	0(A0,D0*4),A0				;GET CASE JUMP ADDRESS
		move.l	a0,modeCase(a6)				;save for later
		bra.s	@gotMode
@useLoops32
		move.l 	stArith32TabPtr,A0			;POINT TO 32 bit MODE TABLE
		bra.s	@getMode

@notArithMode
		MOVE.L	INVERTFLAG(A6),D7			;GET THE INVERT FLAG
		BCLR	#2,D0						;CLEAR INVERT BIT
		CMP 	#7,D0						;IS MODE > 7 ?
		BGT 	DONE						;YES, QUIT
@setupJump
		LEA 	StretchModeTab,A0			;POINT TO MODE TABLE (in trap table)
		MOVE.L	0(A0,D0*4),MODECASE(A6) 	;SAVE FOR LATER
@gotMode

;------------------------------------------------
;
;  SET UP srcMergeCase.
;
@noPromote
	 	move.w	srcshift(a6),d3				;src depth
		lea		VMergeTable,a0				;get base
		add.l	(a0,d3.w*4),a0				;get routine offset from base
		move.l	a0,srcMergeCase(a6)

SourceMergeSetupDone
;------------------------------------------------
;
;  SET UP maskMergeCase
;
		clr.l	CombineMaskCase(a6)			;assume no mask
		clr.l	maskMergeCase(a6)			;assume no mask
		tst.l	maskbits(a6)				;is there a mask?
		beq		nomask1						;=>NO

		move.w	maskshift(a6),d0			;mask depth, currently 0, 4, or 5
		lea		VMergeTable,a0				;get base
		add.l	(a0,d0.w*4),a0				;get displacement to routine
		move.l	a0,maskMergeCase(a6)


MergeSetupDone

;------------------------------------------------
;
;  set up CombineMaskCase
;
		tst		maskshift(a6)
		beq.s	CombineMaskSetupDone		;one bpp mask
;
; Table is disorganized as follows:
;
;	SRC		DST		MASK	ENTRY
;	32		ind		32		0
;	32		16		32		1
;	32		32		32		2
;
; calc routine based on dst
;
;
; want indexed values to goto 0, 16 bit to 1, 32 bit to 2
;
		move	dstshift(a6),d0
		subq	#3,d0
		spl		d1
		and		d1,d0

		lea		CombineTable,a0				;get base
		add.l	(a0,d0.w*4),a0				;get displacement to routine
		move.l	a0,CombineMaskCase(a6)

CombineMaskSetupDone

;------------------------------------------------
;
;  SET UP MASKALIGN AND MASKADDR IF THERE IS A MASK
;

		MOVE	MASKSHIFT(A6),D3			;GET MASKSHIFT
		LEA		MASKPIX(A6),A2				;POINT TO MASKPIX
		MOVE.L	MASKROW(A6),D2				;GET MASK ROWBYTES

		MOVE.L	MASKRECT(A6),A0				;POINT TO MASKRECT
		MOVE	LEFT(A0),D1 				;GET MASKRECT LEFT
		SUB 	BOUNDS+LEFT(A2),D1			;CONVERT TO MASK GLOBAL
		EXT.L	D1							;MAKE LONG FOR BIG PIXELS
		lsl.l	d3,d1						;convert pixels to bits
		MOVEQ	#$1F,D5						;TREAT MOD 32 FOR MASKALIGN
		AND.L	D1,D5						;MAKE A COPY
		MOVE.L	D5,MASKALIGN(A6)			;SAVE ALIGNMENT OF MASK

		MOVE	TOP(A0),D0					;GET MASKRECT TOP
		SUB 	BOUNDS+TOP(A2),D0			;CONVERT TO MASK GLOBAL
		MULS	D2,D0 						;MULT BY MASK ROWBYTES			BAL 02Dec88
		ADD.L	BASEADDR(A2),D0 			;GET START OF MASK BITMAP

		SUB.L	D5,D1						;ADJUST MASKLEFT FOR MASKALIGN
		ASR.L	#3,D1						;CONVERT BITS TO BYTES
		ADD.L	D1,D0						;ADD BYTES TO MASKADDR
		MOVE.L	D0,MASKADDR(A6)				;SAVE AS MASKADDR


NOMASK1
;----------------------------------------------------------
;
;  Jump into 32 bit addressing mode for blitting.								@@@@	BAL	09Apr88
;

		moveq	#true32b,d0					;switch to 32 bit addressing		@@@@	BAL	09Apr88
		_rSwapMMUMode			;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.b	d0,MMUsave(a6)				;save previous state for later		@@@@	BAL	09Apr88


;------------------------------------------------
;
;  SET UP SRCROW, SRCSCANS, SRCSHIFT, AND SRCADDR
;
		MOVE	realSRCSHIFT(A6),D3			;GET SRCSHIFT
		LEA		SRCPIX(A6),A2				;POINT TO SRCPIX
		MOVE.L	SRCROW(A6),D2				;GET SRC ROWBYTES

		MOVE	BOUNDS+BOTTOM(A2),D1		;GET SRCBITS.BOUNDS.BOTTOM
		SUB 	BOUNDS+TOP(A2),D1			;MAKE IT GLOBAL
		MOVE	D1,SRCSCANS(A6)				;SAVE NUMBER OF SCANS TO DO

		MOVE.L	SRCRECT(A6),A0				;POINT TO SRCRECT
		MOVE	LEFT(A0),D1 				;GET SRCRECT LEFT
		SUB 	BOUNDS+LEFT(A2),D1			;CONVERT TO SRC GLOBAL
		EXT.L	D1							;MAKE LONG FOR BIG PIXELS
		LSL.L	D3,D1						;CONVERT SRC PIXELS TO BITS
		MOVEQ	#$1F,D5						;TREAT MOD 32 FOR SRCSHIFT
		AND.L	D1,D5						;MAKE A COPY
		MOVE.L	D5,SRCALIGN(A6)				;SAVE ALIGNMENT OF SOURCE

		MOVE	TOP(A0),D0					;GET SRCRECT TOP
		SUB 	BOUNDS+TOP(A2),D0			;CONVERT TO SRC GLOBAL
		MULS	D2,D0 						;MULT BY SRC ROWBYTES			BAL 02Dec88
		ADD.L	BASEADDR(A2),D0 			;GET START OF SRC BITMAP

		SUB.L	D5,D1						;ADJUST SRCLEFT FOR SRCSHIFT
		ASR.L	#3,D1						;CONVERT BITS TO BYTES
		ADD.L	D1,D0						;ADD BYTES TO SRCADDR
		MOVE.L	D0,SRCADDR(A6)				;SAVE AS SRCADDR

	if 0 then

; If srcAlign is a multiple of 8 there is no reason to make a copy of the src.	<BAL 17Mar89>

		tst		d5

;		and		#7,d5						;alignment required?				<BAL 17Mar89>
		bra.s	@mustAlign
		clr.l	SRCALIGN(A6)				;remember to skip alignment pass	<BAL 17Mar89>
		clr.l	dstBufBump(A6)				;init to no bump					<BAL 17Mar89>
		clr.l	scaleBufBump(A6)			;init to no bump					<BAL 17Mar89>
		move.l	SRCBUF(A6),d1				;REMEMBER WHERE SRCBUF was			<BAL 17Mar89>
		move.l	srcRow(a6),d2
		sub.l	d2,d0						;anticipate initial bump			<BAL 17Mar89>
		move.l	d0,srcBuf(a6)				;use srcAddr as srcBuf				<BAL 17Mar89>
		cmp.l	DSTBUF(A6),d1 				;is dstBuf same as srcBuf?			<BAL 17Mar89>
		bne.s	@mustAlign
		move.l	d0,dstBuf(a6)				;use srcAddr as dstBuf				<BAL 17Mar89>
		move.l	d2,dstBufBump(a6)			;set up rowBump for dstBuf			<BAL 17Mar89>
		cmp.l	SCALEBUF(A6),d1 			;is scaleBuf same as srcBuf?		<BAL 17Mar89>
		bne.s	@mustAlign
		move.l	d0,scaleBuf(a6)				;use srcAddr as scaleBuf			<BAL 17Mar89>
		move.l	d2,scaleBufBump(a6)			;set up rowBump for scaleBuf		<BAL 17Mar89>

	endif

@mustAlign
;----------------------------------------------------
;
;  CALC STARTING DSTROW, DSTSHIFT, AND DSTADDR
;
		MOVE	DSTSHIFT(A6),D4				;GET DST SHIFT
		MOVE.L	DSTROW(A6),D2				;GET DST ROWBYTES

		MOVE.L	DSTRECT(A6),A0
		MOVE	TOP(A0),VERT(A6)			;INIT CURRENT VERTICAL
		MOVE	LEFT(A0),D1 				;GET DSTRECT LEFT
		SUB 	BOUNDS+LEFT(A5),D1			;CONVERT TO GLOBAL COORDS
		EXT.L	D1							;MAKE LONG FOR BIG PIXELS
		LSL.L	D4,D1						;CONVERT DST PIXELS TO BITS
		MOVEQ	#$1F,D6
		AND.L	D1,D6						;TREAT MOD 32 FOR SHIFTCNT
		NEG.L	D6							;AND NEGATE IT
		MOVE.L	D6,DSTALIGN(A6)				;SAVE FOR LATER

		MOVE.L	D6,D0						;GET ALIGNMENT
		ASR.L	D4,D0						;CONVERT TO PIXELS
		MOVE.L	D0,DSTMASKALIGN(A6)			;AND SAVE FOR MASK

		MOVE	MINRECT+TOP(A6),D0			;GET MINRECT TOP
		SUB 	BOUNDS+TOP(A5),D0			;CONVERT TO GLOBAL COORDS
		MULS	D2,D0 						;MULT BY DST ROWBYTES			BAL 02Dec88
		ADD.L	BASEADDR(A5),D0 			;GET START OF DST BITMAP

		ASR.L	#5,D1						;CONVERT BITS TO LONGS
		LSL.L	#2,D1						;AND BACK TO BYTES (MOD 4)
		ADD.L	D1,D0						;ADD BYTES TO DSTADDR
		MOVE.L	D0,DSTADDR(A6)				;SAVE AS DSTADDR

		_stScanLoop



stScanLoop
;-----------------------------------------------------
;
;  Perform quick checks to see if we can use special cases
;

		if 0 then							;<14SEP90 SMC>

		tst.b	FastCase(a6)				;FG Black, BG White, no scaling, copy mode, no mask?
		beq.s	@goSlow						;no, must go slow

		CMP.W	#8,DSTPIX+PIXELSIZE(A6)		;destination 8 bits/pixel?
		BNE.S 	@ChkDst1Bit					;if not, skip

		CMP.W	#8,SRCPIX+PIXELSIZE(A6)		;src 8 bits/pixel?
		BEQ	 	CB8to8Clip					;yes, go fast

		CMP.W	#1,SRCPIX+PIXELSIZE(A6)		;src 1 bits/pixel?
		BNE.S	@goSlow
		move.l	ExTblPtr,A0					;POINT TO ROUTINE TABLE
		add.l	3*4(A0),A0					;get 1 to 8 bit routine
		CMP.L	ScaleCase(a6),a0			;standard 1 bit src?
		BNE.S	@goSlow
		BRA		CB1to8Clip

@ChkDst1Bit
		CMP.W	#1,DSTPIX+PIXELSIZE(A6)		;destination 8 bits/pixel?
		BNE.S 	@goSlow						;if not, can't handle

		CMP.W	#8,SRCPIX+PIXELSIZE(A6)		;src 8 bits/pixel?
		BEQ	 	CB8to1Clip					;if not, skip
@goSlow

		endif								;<14SEP90 SMC>

;-----------------------------------------------------
;
;  INIT ERROR TERM FOR DDA
;
		MOVE	DENOM+V(A6),D0		;get source height						<5MAR90 KON>
		cmp.w	Numer+v(a6),d0		;check against destination height		<5MAR90 KON>
		ble.s	Expand				;src height <= destination : stretch	<5MAR90 KON>
		move	d0,d1				;save source height						<5MAR90 KON>
		ext.l	d1					;
		divu.w	numer+v(a6),d1		;src MOD dst to high word of d1			<5MAR90 KON>
		swap	d1					;get remainder in low word				<5MAR90 KON>
		tst		d1					;exact shrink?							<5MAR90 KON>
		bne.s	Expand				; no, use general error					<5MAR90 KON>
		sub.w	#1,d0				;yes, use src height-1					<5MAR90 KON>
		bra.s	Expand1
Expand
		lsr		#1,d0
Expand1
		neg		d0
		move	d0, verror(a6)
		move	d0, maskerror(a6)

;
; Calc num destinations to skip, put in D1
;
SKIPDST
		moveq	#0,d3						;assume starting on line 0 in source
		move.l	srcaddr(A6),a3				;get source address in register
		MOVE	MINRECT+TOP(A6),D1 			;
		SUB 	VERT(A6),D1					;Clipped scans at top
		BLE		@DontSkipSource				;no, DST NOT CLIPPED
;
; Skip source while error is negative, D3 contains number of source scans to skip
;
@nxtSrc	MOVE.L	MASKROW(A6),D0				;GET MASK ROWBYTES
		ADD.L	D0,MASKADDR(A6)				;BUMP MASK TO NEXT ROW, even if there isn't one
		MOVE.L	SRCROW(A6),D2				;GET SRC ROWBYTES

		ADD.L	D2,a3						;BUMP SRC TO NEXT ROW
		addq	#1,d3						;number of source scan lines skipped
		MOVE	maskNumer+V(A6),D0			;update mask error: assume same as source
		ADD 	D0,maskError(A6)
		MOVE	numer+V(A6),D0				;GET NUMER.V
		ADD 	D0,verror(A6)				;VERROR := VERROR + NUMER.V
		ble.s	@nxtSrc						;SKIP IF VERROR > 0

;
;Error is +, skip destinations until we've skipped D1 of them
;
		MOVE	DENOM+V(A6),D0			;src height
		move	maskDenom+v(a6),d2
@nxtDst	ADD		#1,VERT(A6)				;BUMP TO NEXT VERTICAL on dest
		sub		d2,maskerror(a6)		;update mask error: assume same as source
		SUB		D0,VERROR(A6)			;VERROR := VERROR - DENOM.V
		subq.w	#1,d1					;dst lines to skip
		ble.s	@ReadyToDraw
		tst.w	VERROR(A6)
		blt.s	@nxtSrc
		bra.s	@nxtDst 					;IF MORE, THEN CONTINUE

@ReadyToDraw
		tst.w	VERROR(A6)					;don't bump further than we need to
		ble.s	@DestIsOK					; <63>
		move.L	SRCROW(A6),D2				;GET SRC ROWBYTES
		sub.L	d2,a3						;bump src to previous row
		move.L	MASKROW(A6),D0				;GET SRC ROWBYTES
		sub.L	D0,MASKADDR(A6)				;BUMP SRC TO NEXT ROW
		subq	#1,d3						;number of source scan lines skipped
		move	NUMER+V(A6),D0				;GET NUMER.V
	if not(TheFuture) then					; <60> Build old code for now
		move	maskDenom+v(a6),d2			; <60>
	endif									; <60>
	if TheFuture then						; <60> New code for later
		move	maskNumer+v(a6),d2			; <59>
	endif									; <60>
		sub		d2,maskerror(a6)
		sub 	D0,VERROR(A6)				;VERROR := VERROR + NUMER.V
		bgt.s	@ReadyToDraw					;


@DestIsOK
;
; here d3 contains number of first src line (# of src lines skipped)
; a3 contains starting address
;
@DontSkipSource
		_pmVersionSrcFirstTime					;D3 contains starting scan line no.
		move.l	a3,srcaddr(a6)					;put src address back

		_pmVersionMaskFirstTime					;D3 contains starting scan line no.
;-----------------------------------------------------
;
;  GET FIRST SCANLINE OF SRC INTO SRCBUF
;
NEXTSRC TST		SRCSCANS(A6)				;ANY SCANS LEFT?
		BLE		DONE						;=>NO, QUIT


;-----------------------------------------------------
;
; 	Do MergeCase moves a line of source into srcbuf and does vertical
;				 averaging if necessary.
;
; Do MergeCase for vertical shrinking of mask
; Do MergeCase for vertical shrinking of src
;
;	Clobbers:  D0-D4,D6,D7,A0,A1
;
DoMergeCase
;
; Calculate 0-based scanline count in d7.
;
		move.l	maskMergeCase(a6),d0
		beq.s	DoSrcMergeCase				;no mask
		move.l	d0,a0

		moveq	#-1,d7
		move	srcscans(a6),d1
		move	masknumer+v(a6),d0
@AnotherLine
		addq	#1,d7
		subq	#1,d1
		blt.s	@maskDone
		add		d0,maskerror(a6)
		ble.s	@AnotherLine				;done when maskerror > 0
@maskDone
		moveq	#0,d4						;clear high word of srclongs	<17JUL90 KON>
		move.w	srcmasklongs(a6),d4
		move.l	maskalign(a6),d5
		move.w	maskPix+pixelSize(a6),d6

		move.l	srcmaskbuf(a6),a2			;dest buffer pointer
		move.l	maskaddr(a6),a3
		move.l	MaskPixPmTable(a6),a4
;		move.l	maskpix+pmTable(a6),a4
;		move.l	(a4),a4						;get pointer to color table
		move.l	maskrow(a6),a5				;row bytes
		jsr		(a0)						;returns to DoSrcMergeCase
		move.l	a3,maskaddr(a6)

DoSrcMergeCase
;
; Calculate 0-based scanline count in d7.
;
		moveq	#-1,d7						;
@AnotherLine
		addq	#1,d7
		subq	#1,srcscans(A6)
		blt.s	@srcScansDone
		move	numer+v(a6),d0
		add		d0,verror(a6)
		ble.s	@AnotherLine				;done when verror > 0
@srcScansDone
		moveq	#0,d4						;clear high word of srclongs	<17JUL90 KON>
		move.w	srclongs(a6),d4
		move.l	srcalign(a6),d5
		move.w	srcPix+pixelSize(a6),d6
		tst.b	realDepth(a6)				;promoting src to RGB?
		bmi.s	@notPromoting				;no, all ok
		move.w	realDepth(a6),d6
@notPromoting
		move.l	srcbuf(a6),a2				;dest buffer pointer
		move.l	srcaddr(a6),a3

		move.l	SrcPixPmTable(a6),a4
;		move.l	(a4),a4						;get pointer to color table
		move.l	srcrow(a6),a5				;row bytes
		move.l	srcMergeCase(a6),a0
		jsr		(a0)
		move.l	a3,srcaddr(a6)
;
; srcbuf is setup and shrunk, do colorizing if necessary.
; this is done when the source is direct and the XLateFlag is setup by mapModeTable
;
		btst	#ColorizeInSrcBufBit, XLateFlag(a6)	; Colorize during expansion?
		beq.s	@ColorizeDone						;branch if no

		move.w	srclongs(a6),d1
		move.l	srcbuf(a6),a2					;dest buffer pointer
		move.l	RGBFrColor(A6),D4				;GET FG COLOR
		move.l	RGBBgColor(A6),D3				;GET BK COLOR
@ColorMe
		move.l	(a2),d2
;
; colorize, the fg/bk are in RGB space and hence switched
;
		move.l	d2,d7					;copy source
		AND.L	D3,D2					;ADD BG COLOR TO SRC
		NOT.L	d7						;GET NOT SRC
		AND.L	D4,d7					;ADD FG COLOR TO NOT SRC
		OR.L	D2,d7					;COMBINE FG/BK DATA

		MOVE.L	d7,(A2)+				;put a long to destination
		DBRA	D1,@ColorMe				;loop for all longs

@ColorizeDone
SRCOK
		MOVE.L	DSTALIGN(A6),D6				;RESTORE DSTALIGN
		MOVE.L	INVERTFLAG(A6),D7			;RESTORE INVERT FLAG

;----------------------------------------------------------
;
;  HORIZONTALLY STRETCH SRCBUF INTO DSTBUF
;
;  USES:	D0:(CLOBBERED)	D1:(CLOBBERED)	D2:(CLOBBERED)	D3:(CLOBBERED)
;			D4:(CLOBBERED)	D5:(DSTPIXSIZE)	D6:!DSTALIGN	D7:!(INVERTFLAG)
;			A0:(CLOBBERED)	A1:(CLOBBERED)	A2:(MASKADDR)	A3:(CASEJUMP)
;			A4:(SRCLONGS)	A5:				A6:				A7:
;
		MOVE	NUMER+H(A6),D0				;GET DST WIDTH
		CMP		DENOM+H(A6),D0				;SAME AS SRC WIDTH?
		BEQ.S	SOK							;=>YES, NO STRETCHING NEEDED
		MOVE	DSTLONGS(A6),D0 			;GET DSTLONGS
		MOVE.L	SRCBUF(A6),A0				;POINT TO SRCBUF
		MOVE.L	DSTBUF(A6),A1				;POINT TO DSTBUF
		LEA 	4(A1,D0*4),A2 				;SET UP DSTLIMIT
		MOVE	HORIZFRACTION(A6),D4 		;GET HORIZONTAL FRACTION
		MOVE	SRCPIX+PIXELSIZE(A6),D5		;GET SIZE OF DST PIXELS (= SRC PIXELS)
;
; if it's a deep mask and the pixel depth is 16, then it's really 32 bpp
;
		cmp		#16,d5
		bne.s	@allok
		move.w	maskshift(a6),d2			;deep mask?
		cmp		#4,d2
		blt.s	@allok						;not deep mask, don't change pix depth
		move.w	#32,d5						;really 32 bpp
@allok
		MOVE.L	RATIOCASE(A6),A3			;GET CASE JUMP
		MOVEQ	#0,D0						;CASE JUMP ROUTINE USES BYTE
		JSR 	(A3)						;AND CALL STRETCHROW


;----------------------------------------------------------
;
;  HORIZONTALLY STRETCH SRCMASKBUF INTO DSTMASKBUF
;
;  USES:	D0:(CLOBBERED)	D1:(CLOBBERED)	D2:(CLOBBERED)	D3:(CLOBBERED)
;			D4:(CLOBBERED)	D5:(DSTPIXSIZE)	D6:!DSTALIGN	D7:!(INVERTFLAG)
;			A0:(CLOBBERED)	A1:(CLOBBERED)	A2:(MASKADDR)	A3:(CASEJUMP)
;			A4:(SRCLONGS)	A5:				A6:				A7:
;
SOK		MOVE	MASKNUMER+H(A6),D0			;GET DSTMASK WIDTH
		CMP		MASKDENOM+H(A6),D0			;SAME AS SRCMASK WIDTH?
		BEQ.S	@DoMasking					;=>YES, NO STRETCHING NEEDED
		MOVE	DSTMASKLONGS(A6),D0 		;GET NUMBER OF LONGS
		MOVE.L	SRCMASKBUF(A6),A0			;POINT TO SRCMASKBUF
		MOVE.L	DSTMASKBUF(A6),A1			;POINT TO DSTMASKBUF
		LEA 	4(A1,D0*4),A2 				;SET UP DSTLIMIT
		MOVE	MASKFRACT(A6),D4 			;GET HORIZONTAL FRACTION
		MOVE	maskpix+pixelsize(a6),d5	;***GET PIXELSIZE
		cmp.w	#1,d5						;is it 1?
		beq.s	@sizeok						;if yes, leave it alone
		moveq	#32,d5						;otherwise it's really 32
@sizeok
		MOVE.L	MASKCASE(A6),A3				;GET CASE JUMP
		MOVEQ	#0,D0						;CASE JUMP ROUTINE USES BYTE
		JSR 	(A3)						;AND CALL STRETCHROW

@DoMasking
;----------------------------------------------------------
;
;  Combine src and dest using mask.  Only called for deep masks
;
;  USES:	D0:				D1:				D2:					D3:
;			D4:				D5:!dstAlign	D6:dst pixel size	D7:pixel count
;			A0: scratch		A1:mask ptr		A2:destination		A3: src and dst ptr
;			A4: src pmtable	A5: not used	A6: not used		A7: not used
;
		move.l	CombineMaskCase(a6),d0
		beq.s	dstok						;no mask merging
		move.l	d0,a0						;merge routine address

		move.l	dstalign(a6),d5				;get !dstalign
		neg.l	d5

		move.l	dstbuf(a6),a3
		move	numer+h(a6),d7				;number of pixels to do (width of dest)
		move.l	dstmaskbuf(a6),a1
		move.l	dstaddr(a6),a2				;destination
		move.l	dstPix+pmTable(a6),a4
		move.l	(a4),a4						;get clutptr

		move.w	dstpix+pixelsize(a6),d6		;1, 2, 4, 8, 16, 32

		jsr		(a0)						;combine src w/ dst using mask


;----------------------------------------------------------
;
;  Change dstbuf depth to destination depth and put result in scalebuf
;
;  USES:	D0:(CLOBBERED)	D1:(CLOBBERED)	D2:(CLOBBERED)	D3:!(SRCPIXSIZE)
;			D4:!(DSTPIXSIZE)D5:(CLOBBERED)	D6:!DSTALIGN	D7:!INVERTFLAG
;			A0:(DSTBUF)		A1:(SCALEBUF)	A2:(DSTLIMIT)	A3:
;			A4:!(SCALETBL)	A5:!			A6:!			A7:!
;
DSTOK	move.l	dstalign(a6),d6
		MOVE.L	INVERTFLAG(A6),D7			;GET THE INVERT FLAG
		MOVE.L	SCALECASE(A6),D1			;NEED TO EXPAND PIXELS?
		BEQ.S	NXTMASK						;=>NO, DON'T BOTHER STRETCHING
		MOVE	SRCPIX+PIXELSIZE(A6),D3		;GET SOURCE PIXEL SIZE
;
; if it's a deep mask and the pixel depth is 16, then it's really 32 bpp
;
		cmp		#16,d3
		bne.s	@allok
		tst.w	maskshift(a6)				;deep mask?
		beq.s	@allok						;not deep mask, don't change pix depth
		move.w	#32,d3						;really 32 bpp
@allok

		MOVE	DSTPIX+PIXELSIZE(A6),D4		;GET DST PIXEL SIZE
		MOVE.L	DSTBUF(A6),A0				;POINT TO SRC
		MOVE.L	SCALEBUF(A6),A1				;POINT TO DST
		MOVE	SCALELONGS(A6),D0 			;GET SIZE
		LEA 	4(A1,D0*4),A2 				;SET UP DSTLIMIT
		MOVE.L	D1,A3						;GET CASE JUMP ROUTINE
		MOVE.L	ScaleTbl(A6),A4				;POINT TO TRANSLATION TABLE
		MOVEQ	#0,D0						;CASE JUMP ROUTINE USES BYTE
		JSR 	(A3)						;AND CALL STRETCHROW


;-------------------------------------------------------
;
;  TRANSFER ONE OR MORE COPIES OF SCALEBUF INTO DSTBITS
;
;  USES:	D0:				D1:				D2:				D3:!(FGCOLOR)
;			D4:!(BKCOLOR)	D5:arith stuff	D6:!DSTALIGN	D7:!INVERTFLAG
;			A0:				A1:				A2:				A3:
;			A4:				A5:arith stuff	A6:				A7:
;
NXTMASK MOVE.L	FCOLOR(A6),D3				;GET FG COLOR
		MOVE.L	BCOLOR(A6),D4				;GET BK COLOR
		BTST	#5,locMode+1(A6)			;an arithmetic mode?
		BEQ.S	@skipArith

		MOVEQ	#0,D7
		MOVE	dstPix+pixelSize(A6),D7		;get the number of bits in a pixel
		MOVEQ	#32,D5
		DIVU	D7,D5						;# of pixels in a long

	if 0 then		; don't colorize arithmetic modes anymore
; color the source first
; color only if colorizing in mode case

@doColor
		BTST	#ColorizeInModeCaseBit, XLateFlag(a6)
		beq.s	@skipColor

		cmp		#36,locMode(A6)				;transparent mode?  ** should be an equ **   <<PB465 BAL>>
		beq.s	@skipColor					;if so, skip colorizing.  <KON>

		MOVE.L	SCALEBUF(A6),A3				;INIT SRCPTR
		MOVE	BUFSIZE(A6),D2				;INIT COUNT OF LONGS
@nxtSrc
		MOVE.L	(A3),D0						;get a long from source
		move.l	d0,d1
		AND.L	D3,D0						;ADD FG COLOR TO SRC
		NOT.L	d1							;GET NOT SRC
		AND.L	D4,d1						;ADD BK COLOR TO NOT SRC
		OR.L	D0,d1						;COMBINE FG/BK DATA
		move.l	d1,(A3)+					;write it out
		SUB		D5,D2						;do for all of the pixels on this row
		BGE.S	@nxtSrc
@skipColor
	endif

		MOVE.L	colorTable(A6),A5			;set up for arithmetic modes
		CMP		#$24,locMode(A6)			;transparent?
		BNE.S	@skipArith					;if not, regs are fine
		BFEXTU	transColor(A6){0:D7},D0
		MOVE.L	D0,A5
@skipArith

NXTMSK1	MOVE	VERT(A6),D0 				;GET CURRENT VERT COORD
		CMP 	MINRECT+TOP(A6),D0			;IS VERT < MINV ?
		BLT.S	NODRAW						;YES, DON'T DRAW
;
; if mask is >1 bit/pixel, trick seek into ignoring mask by zeroing dstmaskbuf
;
		move.l	dstmaskbuf(a6),a4			;save dstmaskbuf		<KON 9JAN90>
		tst		maskshift(a6)
		beq.s	@NoTrickorTreat
		clr.l	dstmaskbuf(a6)				;make seek think there is no mask
@NoTrickorTreat
		JSR 	([SEEKMASK,A6])				;MAKE MASK BUFFER CURRENT

		move.l	a4,dstmaskbuf(a6)			; 						<KON 9JAN90>

		MOVE.L	SCALEBUF(A6),A3				;INIT SRCPTR
		MOVE.L	DSTADDR(A6),A4				;INIT DSTPTR FOR ROW
		MOVE.L	RGNBUFFER(A6),A2			;INIT MASKPTR FOR ROW
		MOVE	BUFSIZE(A6),D2				;INIT COUNT OF LONGS
		MOVE.L	MODECASE(A6),A0 			;GET MODE CASE JUMP
		BTST	#5,locMode+1(A6)			;an arithmetic mode?
		BEQ.S	@skipArith
		MOVE.L	transColor(A6),D4			;set up transparent color in case different from bg
		CMP		#$24,locMode(A6)			;transparent?
		BEQ.S	@skipInvTbl					;if so, D5 contains the pixels per long value
		MOVE	invSize(A6),D5				;set up resolution of inverse table for arith. modes
@skipInvTbl
		MOVEQ	#0,D3						;initialize destination pixel offset
		MOVE.L	dstAlign(A6),D6				;reset alignment since it is bumped by arith. modes
		SUB.L	D7,D6						;bump source pixel offset back by 1
@skipArith
		CMP.L	DSTPIX+BASEADDR(A6),A4		;IS IT BEFORE THE PIXMAP?
		BLO.S	DSTNEG						;=>YES, DON'T PUT TO DST
DOBLT	JMP 	(A0)						;TAKE MODE JUMP
NEXTDST MOVE.L	DSTROW(A6),D0				;GET DST ROWBYTES
		ADD.L	D0,DSTADDR(A6)				;BUMP DST TO NEXT ROW

NODRAW	ADD 	#1,VERT(A6) 				;BUMP TO NEXT VERT
		MOVE	VERT(A6),D0 				;GET VERT
		CMP 	MINRECT+BOTTOM(A6),D0		;ARE WE AT THE LAST SCAN LINE ?
		BEQ.S	DONE						;YES, QUIT
		MOVE	maskdenom+V(A6),D0			;update mask error
		SUB 	D0,maskERROR(A6)
		MOVE	DENOM+V(A6),D0
		SUB 	D0,VERROR(A6)				;VERROR := VERROR - DENOM.V
		BLT 	NEXTSRC 					;IF VERROR < 0 THEN GET NEXT SRC				<BAL 19Mar89>
		tst.b	useDither(a6)				; are we dithering?								<BAL 19Mar89>
		bne.s	dstOK						; yes dither this scan again with current error	<BAL 19Mar89>
		BRA 	NXTMSK1 					;ELSE continue to draw from this src			<BAL 19Mar89>

;-----------------------------------------------------------------
;
;  HANDLE CASE WHERE DST IS NEGATIVE
;
DSTNEG	MOVE.L	DSTPIX+BASEADDR(A6),D1		;GET ELUSIVE BASE ADDRESS
		BTST	#5,locMode+1(A6)			;AN ARITHMETIC MODE?
		BEQ.S	@NoRith						;=>NOPE, DO NORMAL

; IF ARITHMETIC MODE, BUMP ONE PIXEL AT A TIME UNTIL DST ISN'T NEGATIVE

@LOOP	LEA		0(A4,D3),A1					;GET CURRENT ADDRESS
		CMP.L	A1,D1						;ARE WE STILL NEGATIVE?
		BLS.S	DOBLT						;=>NO, BLIT REST OF SCANLINE
		SUBQ	#1,D2						;SKIP A DOT
		BMI.S	NEXTDST						;=>DONE WITH SCANLINE
		ADD.L	D7,D6						;BUMP SRC POINTER ONE DOT
		ADD.L	D7,D3						;BUMP DST POINTER ONE DOT
		BRA.S	@LOOP						;=>YES, KEEP SKIPPING

; IF NORMAL MODE, BUMP ONE LONG AT A TIME UNTIL DST ISN'T NEGATIVE

@NoRith	LEA		4(A4),A1					;GET NEXT LONG OF DST
		CMP.L	A1,D1						;ARE WE STILL NEGATIVE
		BLS.S	DOBLT						;=>NO, BLIT REST OF SCANLINE
		SUBQ	#1,D2						;SKIP NEXT LONG
		BMI.S	NEXTDST						;=>DONE WITH SCANLINE
		ADDQ.L	#4,A2						;BUMP MASKPTR
		ADDQ.L	#4,A3						;BUMP SRCPTR
		ADDQ.L	#4,A4						;BUMP DSTPTR
		BRA.S	@NoRith						;=>TRY, TRY AGAIN

;-----------------------------------------------------------------
;
;  ENTIRE STRETCHBITS COMPLETE. RESTORE REGS AND STACK AND GO HOME.
;
DoneStretch
DONE	clr.w	QDErr						;signal no error
doneErr	move.b	MMUsave(a6),d0				;get previous MMU state in d0
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
SHOW	MOVE.L	SAVEA5(A6),A5				;RESTORE A5
		TST.B	CRSRFLAG(A6)				;DID WE SHIELD THE CURSOR?
		BEQ.S	GOHOME						;=>NO, JUST RETURN
		_SHOWCURSOR							;RESTORE CURSOR
GOHOME	BSET	#hiliteBit,HiliteMode		;reset hilite override, in case colormap was skipped
		MOVE.L	SAVESTK(A6),SP				;STRIP VARIABLE SIZED BUFFER
		move.l	stackHandle(a6),d0			;did we allocate a handle?
		beq.s	@noTemp						;no, forget it.
		move.l	d0,a0						;pass handle in a0
		_DisposeTempBuffer					;dispose it.
		move.l	saveStkLowPt(a6),stkLowPt	;restart the sniffer	<57>
		move.l	oldHiHeapMark(a6),HiHeapMark ;restore extent of stack
@noTemp	MOVEM.L (SP)+,D0-D7/A1-A5			;RESTORE REGISTERS
		UNLINK	PARAMSIZE,'STRETCHB'


	ALIGN 	Alignment

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

stNoStack
		tst.l	StackFree(a6)				;did we run out of stack?
		bpl.s	SHOW						;no, just go home
		movem.l	d0-d3/a0-a2,-(sp)			;save state
		neg.l	d0							;<BAL and KON 14Feb90>
		move.l	d0,stackFree(a6)			;<BAL and KON 14Feb90>
		tst.l	stackHandle(a6)				;have we been here before?
		bne.s	@noMem						;yes, forget it.

		move.l	HiHeapMark,oldHiHeapMark(a6) ;save extent of stack
		moveq	#4,d0						;						<KON 14Feb90>
		swap	d0							;try for 256K			<BAL 14Feb90>
		_NewTempBuffer						;returns a0=handle, d0=size
		move.l	d0,d2						;copy the actual size
		beq.s	@noMem						;if zero, we didn't get it.
@gotit	move.l	a0,stackHandle(a6)			;remember to dispose it later
		sub.l	#qdStackXtra,d2				;leave room for interrupts
		asr.l	#2,d2						;make cnt of longs
		add.l	d2,stackFree(a6)			;new free cnt
		bmi.s	@noMem						;didn't get enough
		clr.l	stkLowPt					;disable stack sniffer
		move.l	a7,a2						;remember where save regs are
		move.l	(a0),a0						;get ptr
		exg		a0,d0						;get ptr in d0, size in a0
		_rTranslate24To32					;strip it
		move.l	d0,HiHeapMark				;set up stack limit for _stackSpace
		add.l	d0,a0						;point to end of block
		move.l	7*4(a7),-(a0)				;copy over return address
		move.l	a0,a7						;move the stack there

		movem.l	(a2),d0-d3/a0-a2			;restore state
		rts

@noMem	move.w	#nsStackerr,QDErr
		bra.s	SHOW

;******************************************************************************************

;--------------------------------------------
;
;  Source scanline merge routines.
;	There are 3 routines:  OneDeep, NDeep, and Average16and32
;	These routines copy from srcaddr to srcbuf and do vertical 
;	merging of source if necessary.
;
;	When promoting source (ie dither mode) to 32 bit/pixel, Average16and32
;	is called.
;
;  EXPECTS:  D0:			D1:				D2:				D3:
;			 D4:			D5:!SRCALIGN	D6:!DSTALIGN	D7:!INVERTFLAG
;			 A0:			A1:				A2:				A3:
;			 A4:			A5:				A6:				A7:
;--------------------------------------------


VMergeTable
		dc.l	oneDeep-VMergeTable			;src 1-bit/pixel
		dc.l	ndeep-VMergeTable			;src 2-bit/pixel
		dc.l	ndeep-VMergeTable			;src 4-bit/pixel
		dc.l	ndeep-VMergeTable			;src 8-bit/pixel
		dc.l	Average16and32-VMergeTable	;src 16-bit/pixel
		dc.l	Average16and32-VMergeTable	;src 32-bit/pixel

;--------------------------------------------
;
;	Loop to combine d7 pixels of source and dest using mask
;
;	ENTRY:
;	D0:	scratch						A0: scratch
;	D1: scratch						A1: mask ptr
;	D2: scratch						A2: destination
;	D3: scratch						A3: src and dst ptr
;	D4: scratch						A4:	src pmtable 								A5:	rowbytes
;	D5:	srcAlign					A5:	rowbytes
;	D6:	realDepth (pixel size)
;	D7:	byte Count (zero based)
;
;	There are 12 different cases:  all combinations of source and mask
;	being either 16- or 32-bits/pixel and dest being any depth.  A mask 
;	of $ff means take source.  The mask value ranges from 0-$7f,$81-$100.

CombineTable
												;SRC	DST		MASK	ENTRY
		dc.l	Combine32in32-CombineTable		;32		ind		32		0
		dc.l	Combine321632-CombineTable		;32		16		32		1
		dc.l	Combine323232-CombineTable		;32		32		32		2


;*******************************************************************
;
; CombineMaskCase
;
;	Loop to combine d7 pixels of source and dest using mask
;
;ENTRY:
;	D0:	(dst)						A0: address of routine called
;	D1: (src)						A1: mask ptr
;	D2: (dst component)				A2: destination
;	D3: (mask)						A3: src and dst ptr
;	D4: (build pixel)				A4:	src pmtable 								A5:	rowbytes
;	D5:	srcAlign					A5:
;	D6:	realDepth (pixel size)
;	D7:	byte Count (zero based)
;
;	There are 12 different cases:  all combinations of source and mask
;	being either 16- or 32-bits/pixel and dest being any depth.  A mask 
;	of $ff means take source.  The mask value ranges from 0-$7f,$81-$100.
;
;EXIT:
;
;
;*******************************************************************
;
; handle merging with indexed destinations, assume source and mask are 32 bpp
;
;	Promote destination pixel to 32-bits/pixel, combine with source on a
; component by component basis according to value stored in mask
;
Combine32in32
		bfextu	(a2){d5:d6},d0				;get a pixel of destination
		add		d6,d5						;bump to next pixel
		moveq	#0,d4
		move.w	d4,d1						;clear regs
		move.w	d4,d2
		move.w	d4,d3
		move.b	1(a3),d2					;get red of source
		move.b	ctTable+rgb+red(a4,d0.w*8),d1 ;get destination red into virgin reg

		sub.w	d2,d1						;red dst - red source
		move.b	1(a1),d3					;get red mask
		bpl.s	@1
		addq	#1,d3						;make mask go from 0 to 256
@1
		muls.w	d3,d1
		lsl.w	#8,d2						;src*256
		add.w	d2,d1						;(dst-src)*mask+(src*256)
		move.w	d1,d4						;new red component (0000RRXX)
;
; now do green
;
		move.w	#0,d1						;clear regs
		move.w	d1,d2
		move.w	d1,d3
		move.b	2(a3),d2					;get green of source
		move.b	ctTable+rgb+green(a4,d0.w*8),d1 ;get destination green into virgin reg

		sub.w	d2,d1						;green dst - green src
		move.b	2(a1),d3					;get green mask
		bpl.s	@2
		addq	#1,d3						;make mask go from 0 to 256
@2
		muls.w	d3,d1						;(dst-src)*mask
		lsl.w	#8,d2						;src*256
		add.w	d2,d1						;(dst-src)*mask+(src*256)
		lsr.w	#8,d1
		move.b	d1,d4						;move in green component (0000RRGG)
;
; now do blue
;
		move.w	#0,d1						;clear regs
		move.w	d1,d2
		move.w	d1,d3
		move.b	3(a3),d2					;get blue of source
		move.b	ctTable+rgb+blue(a4,d0.w*8),d1 ;get destination green into virgin reg

		sub.w	d2,d1						;blue dst - blue src
		move.b	3(a1),d3					;get green mask
		bpl.s	@3
		addq	#1,d3						;make mask go from 0 to 256
@3
		muls.w	d3,d1						;(dst-src)*mask
		lsl.w	#8,d2						;src*256
		add.w	d2,d1						;(dst-src)*mask+(src*256)
		lsr.w	#8,d1
		lsl.l	#8,d4						;result = 00RRGG00
		move.b	d1,d4						;move in blue component (00RRGGBB)
		MOVE.L	d4,(A3)+					;PUT A LONG TO SRCBUF
		addq	#4,a1						;bump to next mask
		DBRA	D7,Combine32in32				;LOOP FOR ALL LONGS
		rts

;
; Handle when src and mask are 32 bpp, dst is 16 bpp
;
Combine321632
		move.l	maskBC,a0					;get useful Konstantin
Combine321632Loop
		move.l	(a1)+,d5					;get a pixel of mask
		bne.s	@maskNonZero
		addq.l	#4,a3						;mask 0 -> all src so just skip
		addq.l	#2,a2						;bump destination
		dbra	D7,Combine321632Loop		;LOOP FOR ALL LONGS
		rts
@maskNonZero
		move.w	(a2)+,d4					;get a pixel of destination
		cmp.l	d5,a0						;mask $7FFF?
		beq		@Writeout555				;all dst, so write out d4

@DoSlowCase
		move.w	d4,d0						;copy destination pixel
		move.l	(a3),d6						;get a pixel of source

		moveq	#0,d4

		move.w	d4,d1						;clear regs
		move.w	d4,d3
		move.w	d4,d2

		swap	d6
		move.b	d6,d2						;get red of source
		swap	d6

		move.w	d0,d4						;red destination in 14 - 10
		lsr.w	#7,d4						;move red to bits 7 - 3
		and.w	#$00f8,d4					;strip bits 2 - 0
		move.b	d4,d3
		lsr.b	#5,d3						;replicate top 3 bits
		or.b	d3,d4						;merge top five bits with top 3 bits

		sub.w	d2,d4						;red dst - red src
		swap	d5
		move.b	d5,d3						;get red mask
		bpl.s	@1
		addq	#1,d3						;make mask go from 0 to 256
@1
		swap	d5
		muls.w	d3,d4						;d2=(dst-src)*mask
		asr.l	#8,d4						;(dst-src)*mask/256
		add.l	d2,d4						;(dst-src)*mask/256+(src)
		swap	d4							;new red component (00RR0000)
;
; now do green
;
		move.w	d6,d1						;get green of source
		lsr.w	#8,d1						;get green in low byte

		move.w	d0,d2						;green destination in 9 - 5
		lsr.w	#2,d2						;green in bits 7 - 3
		and.w	#$00f8,d2					;strip bits 2 - 0
		move.b	d2,d3
		lsr.b	#5,d3						;replicate top 3 bits
		or.b	d3,d2						;merge top five bits with top 3 bits

		sub.w	d1,d2						;green dst - green src
		move.w	d5,d3						;get green mask
		lsr.w	#8,d3
		tst.b	d3
		bpl.s	@2
		addq	#1,d3						;make mask go from 0 to 256
@2
		muls.w	d3,d2						;d2 = (dst-src)*mask
		lsl.w	#8,d1						;src*256
		add.w	d1,d2						;(dst-src)*mask+(src*256)
		move.w	d2,d4						;move in green component (00RRGGxx)
;
; now do blue
;
		move.w	#0,d1						;clear regs
		move.w	d1,d3
		move.b	d6,d1						;get blue of source

		move.b	d0,d2						;blue destination in 4 - 0
		lsl.w	#3,d2						;green in bits 7 - 3
		and.w	#$00f8,d2					;strip bits 2 - 0
		move.b	d2,d3
		lsr.b	#5,d3						;replicate top 3 bits
		or.b	d3,d2						;merge top five bits with top 3 bits
		sub.w	d1,d2						;blue dst - blue src

		move.b	d5,d3						;get green mask
		bpl.s	@3
		addq	#1,d3						;make mask go from 0 to 256
@3
		muls.w	d3,d2						;(dst-src)*mask
		lsl.w	#8,d1						;src*256
		add.w	d1,d2						;(src-dst)*mask+(dst*256)
		lsr.w	#8,d2
		move.b	d2,d4						;move in blue component (00RRGGBB)
@writeoutPixel
		move.l	d4,(a3)+					;PUT A LONG TO SRCBUF
		dbra	D7,Combine321632Loop		;LOOP FOR ALL LONGS
		rts
@Writeout555
;
; d4 has pixel to write out in 555:  convert to 888 and write it out
;
		moveq	#0,d0
		move.w	d4,d0			;red in 14-10
		and.w	#$7c00,d0
		swap	d0				;red in 31-24
		lsr.l	#7,d0			;red in 23-16
		move.w	d4,d0			;green in 9-5
		and.w	#$03e0,d0
		lsl.w	#6,d0			;green in 15-8
		move.b	d4,d0			;blue in 4-0
		and.b	#$1f,d0
		lsl.b	#3,d0			;blue in 7-0, green in 15-8, red in 23-16
		move.l	d0,d4
		bra.s	@writeoutPixel

;
; Handle when src, mask, dst all 32 bpp
;
Combine323232
		move.l	maskBC,a0					;get useful Konstantin
Combine323232Loop
		move.l	(a1)+,d5					;get a pixel of mask
		bne.s	@maskNonZero				;no, go the hard way
		addq.l	#4,a3						;yes, all src so just skip
		addq.l	#4,a2						;bump dst
		dbra	D7,Combine323232Loop		;LOOP FOR ALL LONGS
		rts
@maskNonZero
		move.l	(a2)+,d4					;get a pixel of destination
		cmp.l	d5,a0						;mask $00FFFFFF?
		beq.s	@WriteoutPixel				;all dst, so write out d4

@DoSlowCase
		move.l	d4,d0						;copy destination pixel
		move.l	(a3),d6						;get a pixel of source

		moveq	#0,d4

		move.w	d4,d1						;clear regs
		move.w	d4,d2
		move.w	d4,d3

		swap	d6
		move.b	d6,d2						;get red of source
		swap	d0
		swap	d6
		move.b	d0,d4						;get a pixel of destination
		swap	d0
		sub.w	d2,d4						;red dst - red src
		swap	d5
		move.b	d5,d3						;get red mask
		bpl.s	@1
		addq	#1,d3						;make mask go from 0 to 256
@1
		swap	d5
		muls.w	d3,d4
		asr.l	#8,d4						;(dst-src)*mask/256
		add.l	d2,d4						;(dst-src)*mask/256+(src)
		swap	d4							;new red component (00RR0000)
;
; now do green
;
		move.w	d6,d1						;get green of source
		move.w	d0,d2						;get a pixel of destination
		lsr.w	#8,d1						;get green in low byte
		lsr.w	#8,d2						;get green in low byte

		sub.w	d1,d2						;green dst - green src
		move.w	d5,d3						;get green mask
		lsr.w	#8,d3
		tst.b	d3
		bpl.s	@2
		addq	#1,d3						;make mask go from 0 to 256
@2
		muls.w	d3,d2						;(dst-src)*mask
		lsl.w	#8,d1						;src*256
		add.w	d1,d2						;(dst-src)*mask+(src*256)
		move.w	d2,d4						;move in green component (00RRGGxx)
;
; now do blue
;
		move.w	#0,d1						;clear regs
		move.w	d1,d2
		move.w	d1,d3
		move.b	d6,d1						;get blue of source
		move.b	d0,d2						;get blue of destination
		sub.w	d1,d2						;blue dst - blue src

		move.b	d5,d3						;get green mask
		bpl.s	@3
		addq	#1,d3						;make mask go from 0 to 256
@3
		muls.w	d3,d2						;(dst-src)*mask
		lsl.w	#8,d1						;src*256
		add.w	d1,d2						;(src-dst)*mask+(dst*256)
		lsr.w	#8,d2
		move.b	d2,d4						;move in blue component (00RRGGBB)
@writeoutPixel
		move.l	d4,(a3)+					;PUT A LONG TO SRCBUF
		dbra	D7,Combine323232Loop		;LOOP FOR ALL LONGS
		rts

;*********************************************************************
;
;	Loop to expand and merge D7 scanlines of indexed pixels
;
;ENTRY:
;	D0:	scratch						A0: scratch ptr
;	D1: scratch						A1: scratch ptr
;	D2: scratch						A2: destination
;	D3: scratch						A3: source
;	D4: src longs					A4:	src pmtable 
;	D5:	srcAlign					A5:	rowbytes
;	D6:	realDepth (pixel size)
;	D7:	Scanline Count (zero based)
;
;EXIT:
;
;	a3: new srcaddr
;
;GLOBALS:	AvgBufPtr(a6), AvgBufSize(a6)
;
;*********************************************************************

NDEEP

; LOOP FOR ALL LONGS IN SRC SCANLINE

		move.l	a3,a0						;point to source
		move.l	a2,a1						;point to destination
		move	d4,d1 						;get count of longs

@Align	bfextu	(a0){d5:0},d0				;get an aligned long of source
		add		#4,a0						;bump to next long
		move.l	d0,(a1)+					;put a long to destination
		dbra	d1,@Align					;loop for all longs

;		add.l	a5,a3						;bump source to next row
		_pmVersion
		subq	#1,d7
		bpl.s	@1
		rts

; do verticle merging
@1
		move	d6,d3						;get pixel depth
		move.w	d4,a4						;save count of longs
NdeepMerge

		move.l	d7,-(sp)					;save count of lines to do
		move.l	a3,a0						;point to source
		move.l	a2,a1						;point to destination
		move	a4,d6						;get long count
		moveq	#0,d4						;start at beginning of long

ndlong	bfextu	(a0){d5:0},d0				;extract a long from source
		move.l	(a1),d1						;get next long from destination

ndpxl	bfextu	d0{d4:d3},d2				;get pixel from source
		bfextu	d1{d4:d3},d7				;get pixel from destination
		cmp.l	d7,d2						;which is greater?
		ble.s	nochng						;only change if source is greater
		bfins	d2,d1{d4:d3}				;replace pixel is destination
NOCHNG	add		d3,d4						;bump to next pixel within long
		and		#$1f,d4						;done with long?
		bne.s	ndpxl						;no, keep looping

		add		#4,a0						;bump src offset
		move.l	d1,(a1)+					;write to destination
		dbra	d6,ndlong					;repeat for all longs

;		add.l	a5,a3						;add rowbytes to src pointer
		_pmVersion
		move.l	(sp)+,d7					;retrieve line count
	 	dbra	d7,NdeepMerge	 			;loop while there are lines left
		rts

;*********************************************************************

	ALIGN 	Alignment

;*********************************************************************
;
;	Loop to expand and merge D7 scanlines (0-based) to direct destination
;
;	Src sizes (d6) of 1-8 are promoted to 32-bit/pixel.
;	Src size (d6) of 16 are carried across to 16-bit destinations.
;
;ENTRY:
;	D0:	scratch						A0: scratch ptr
;	D1: scratch						A1: scratch ptr
;	D2: scratch						A2: destination
;	D3: scratch						A3: source
;	D4: src longs					A4:	src pmtable 								A5:	rowbytes
;	D5:	srcAlign					A5:	rowbytes
;	D6:	realDepth (pixel size)
;	D7:	Scanline Count (zero based)
;
;EXIT:
;
;	a3: new srcaddr
;
;GLOBALS:	AvgBufPtr(a6), AvgBufSize(a6)
;

Average16and32

; First check if only one scanline to be merged;
; If so just copy from srcAddr to SrcBuf, expanding if nec.
; else fill average buffer, calc average and move to srcbuf

		tst.w	d7						;doing more than 1 scanline?
		bne		@Average				;yes, average scan lines

;-------------------------------------------------------------------------
;
; Just copy srcAddr to SrcBuf, expanding pixels if necessary
;
		move.l	d4,d1						;get srclongs
		move.l	a3,a0

;
;	If dithering or averaging an indexed src then expand it to 32 bit/pixel RGB data.
;
		cmp.w	#16,d6						;is srcpix indexed?
		bgt.s	@Align						;32-bit => just copy
		beq.s	@Align0						;16-bit => just copy
;
; if there is no color table, ramp each entry between the foreground and background color.
;
		tst.l	a4							;color table?
		beq.s	@NoCTab

@Xpand	BFEXTU	(A0){D5:D6},D0				;get a pixel of src
		add		d6,d5						;bump to next pixel
		move.l	ctTable+rgb+red(a4,d0.w*8),d2 ;get RRRRGGGG in d2
		lsr.l	#8,d2						;get 00RRRRGG
		lsl.w	#8,d2						;get 00RRGG00
		move.b	ctTable+rgb+blue(a4,d0.w*8),d2 ;get 00RRGGBB in d2
		MOVE.L	d2,(A2)+					;put a long to destination
		DBRA	D1,@Xpand					;loop for all longs
		bra		@SrcBufFull

@NoCTab	BFEXTU	(A0){D5:D6},D0				;get a pixel of src
		add		d6,d5						;bump to next pixel

;
; replicate pixel first to 8 bits and then to 24
;
		move.w	d0,d3
		MOVEQ	#8,D2						;replicate to byte size
@NXTPXL	SUB		D6,D2						;SAY WE'VE DONE A PIXEL
		BLE.S	@RepDone					;=>IT WAS THE LAST ONE
		LSL.w	D6,D0						;replicate
		OR.w	D3,D0						;INSTALL FG PIXEL
		BRA.S	@NXTPXL						;=>DO ENTIRE LONG
; d0 has xxxxxxBB
@RepDone
		not.b	d0							;invert it since 00 = black in RGB and white in index
		moveq	#0,d2						;clear high 8 bits
		move.b	d0,d2
		swap	d2
		move.b	d0,d2
		lsl.w	#8,d2
		move.b	d0,d2
		MOVE.L	d2,(A2)+					;put a long to destination
		DBRA	D1,@NoCTab					;loop for all longs
		bra.s	@SrcBufFull




@Align0
;
; promote 16-bit src/mask to 32 bit if deep mask
;
		tst		d5							;alignment
		beq.s	@Align
		addq	#2,a0						;do alignment of 16 bit
@Align
		tst.w	maskshift(a6)				;promote 16 if deep mask
		beq.s	@CopyLoop					;
		cmp.w	#16,d6						;16 bit?
		bne.s	@CopyLoop
;
; Promote 16 bit to 32 bit using existing Scale16to32 routine
;
; a0 ptr to src
; a1 ptr to beginning of dst
; a2 ptr to end of dst
;
		move.l	a2,a1						;get beginning of dst
		addq	#1,d4						;make destination 1-based
		lsl.l	#2,d4						;calc size of dst: longs->bytes *4 	<7JULY90 KON>
		add.l	d4,a2						;calc end of dst ptr
;		add.l	a5,a3						;bump source to next row
		_pmVersion
		jmp		Scale16to32					;inherits return address

@CopyLoop
		move.l	(a0)+,(a2)+					;copy source to destination
		dbra	D1,@CopyLoop				;loop for all longs

@SrcBufFull
;		add.l	a5,a3						;bump source to next row
		_pmVersion
		rts

;------------------------------------------------------------------------


@Average
;
; average 16 or 32 bit source
;
useAverageBuf
		moveq	#0,d1						;get a useful constant

; Init R-G-B accumulation buffer to zero

		move.w	ABufSize(a6),d0				;get count of longs in buffer
		move.l	AvrgBuf(a6),a0				;point at buffer
@1		move.l	d1,(a0)+					;clear it out
		dbra	d0,@1

;
; Are we averaging 16-bit or 32-bit data?
;
		move.w	d7,-(sp)					;save scanline count
		cmp		#16,d6						;16-bit data?
		beq		NextAverageV16				;YES: do 16-bit average loop

; Top of 32-bit scanline averaging loop

NextAverageV32

; loop for all longs in source scanline

		move.l	d5,d2						;GET SHIFT FOR SRC ALIGNMENT
		move.l	a3,a0						;point to source buffer
		move.l	AvrgBuf(A6),A1				;point to accumulation buffer
		move	d4,d3						;get count of source

;-------------------------------------------------------------------------
;
;	If dithering or averaging an indexed src then first pre-Expand it
;	to 32 bit/pixel RGB data.
;
		cmp.w	#32,d6						;promoting src to RGB?
		beq		@NDLONG0					;no, all ok
;
; if no color table, use grey scale
;
		tst.l	a4							;color table?
		beq.s	@NoCTab

@Xpand	BFEXTU	(a0){D2:D6},D0				;get a pixel of src
		add		d6,d2						;bump to next pixel
		move.l	ctTable+rgb+red(a4,d0.w*8),d1 ;get	RRrrGGgg
		swap	d1							;get	GGggRRrr
		lsr.w	#8,d1						;get 	GGgg00RR
		add.w	d1,(a1)+					;accumulate red value
		swap	d1							;get	00RRGGgg
		lsr.w	#8,d1						;get	00RR00GG
		add.w	d1,(a1)+					;accumulate green value
		move.b	ctTable+rgb+blue(a4,d0.w*8),d1 ;get	00RR00BB
		add.w	d1,(a1)+					;accumulate blue value
		dbra	d3,@Xpand					;LOOP FOR ALL LONGS
;		add.l	a5,a3						;bump to next source row
		_pmVersion
		dbra	d7, NextAverageV32			;accumulate d7 scanlines
		bra		MakeAverage


@NoCTab	BFEXTU	(A0){D5:D6},D0				;get a pixel of src
		add		d6,d5						;bump to next pixel

;
; replicate pixel first to 8 bits and then to 24
;
		move.w	d0,d1
		MOVEQ	#8,D2						;replicate to byte size
@NXTPXL	SUB		D6,D2						;SAY WE'VE DONE A PIXEL
		BLE.S	@RepDone					;=>IT WAS THE LAST ONE
		LSL.w	D6,D0						;replicate
		OR.w	D1,D0						;INSTALL FG PIXEL
		BRA.S	@NXTPXL						;=>DO ENTIRE LONG
; d0 has xxxxxxBB
@RepDone
		not.b	d0							;invert it since 00 = black in RGB and white in index
		and.w	#$00FF,d0
		add.w	d0,(a1)+					;accumulate red value
		add.w	d0,(a1)+					;accumulate green value
		add.w	d0,(a1)+					;accumulate blue value
		dbra	d3,@NoCTab					;LOOP FOR ALL LONGS
;		add.l	a5,a3						;bump to next source row
		_pmVersion
		dbra	d7, NextAverageV32			;accumulate d7 scanlines
		bra.s	MakeAverage

;------------------------------------------------------------------------
;
; 
;
@NDLONG0
		moveq	#0,d1
		moveq	#0,d2						;use for extending to word data
		moveq	#0,d5

@NDLONG	move.l	(a0)+,D0					;EXTRACT A LONG FROM SRC
		move.b	d0,d1						;pick up blue component as a word

		lsr.l	#8,d0						;toss blue
		move.b	d0,d2						;pick up green component as a word

		lsr.l	#8,d0						;toss green
		move.b	d0,d5						;pick up red component as a word
		add.w	d5,(a1)+					;accumulate blue value
		add.w	d2,(a1)+					;accumulate green value
		add.w	d1,(a1)+					;accumulate red value
		DBRA	d3,@NDLONG					;=>REPEAT FOR ALL LONGS
;		add.l	a5,a3						;bump to next source row
		_pmVersion
		dbra	d7, NextAverageV32			;accumulate d7 scanlines

MakeAverage
		move.w	(sp)+,d7					;restore scanline count (0-based)
		addq	#1,d7						;make it 1 based

; Now we must compute the average of the accumulated R-G-B's

		move.l	a2,a1						;pointer to destination buffer
		move.l	AvrgBuf(A6),A0				;point to accumulation buffer
		move	d4,d3						;longs in source

		cmp.w	#2,d7						;merged exactly 2 scanlines?
		beq.s	@useShift					;avoid division by using a shift

@hardWay
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up red accumulation
		divu.w	d7,d1						;get red average
		move.b	d1,d0						;put in low byte of pixel		<KON MAY90>
		lsl.l	#8,d0						;make room for next component

		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up green accumulation
		divu.w	d7,d1						;get green average
		move.b	d1,d0						;put in low byte of pixel
		lsl.l	#8,d0						;make room for next component

		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up blue accumulation
		divu.w	d7,d1						;get red average
		move.b	d1,d0						;put in low byte of pixel
		move.l	d0,(a1)+					;dump pixel into destination
		dbra	d3,@hardWay					;loop for all src longs
		rts

@useShift
		moveq	#0,d0						;zero alpha channel				<KON MAY90>
		move.w	(a0)+,d1					;pick up red accumulation
		lsr.w	#1,d1						;get red average
		move.b	d1,d0						;put in low byte of pixel		<KON MAY90>
		lsl.l	#8,d0						;make room for next component
		move.w	(a0)+,d1					;pick up green accumulation
		lsr.w	#1,d1						;get green average
		move.b	d1,d0						;put in low byte of pixel
		lsl.l	#8,d0						;make room for next component
		move.w	(a0)+,d1					;pick up blue accumulation
		lsr.w	#1,d1						;get red average
		move.b	d1,d0						;put in low byte of pixel
		move.l	d0,(a1)+					;dump pixel into srcBuf
		dbra	d3,@useShift				;loop for all src longs
		rts

;-------------- Top of 16-bit average loop -----------------
; Top of 16-bit scanline averaging loop
;	d7 and word at top of stack is number of scanlines to merge
;
NextAverageV16

;
; loop for all longs in source scanline
;
		move.l	a3,a0						;get source address
		move.l	AvrgBuf(A6),A1				;point to accumulation buffer
		move	d4,d5						;get count of source
		moveq	#0,d1						;use for extending to word data
		moveq	#0,d2						;use for extending to word data
		moveq	#0,d3						;use for extending to word data

;------------------------------------------------------------------------

@NDLONG	move.l	(A0)+,D0					;EXTRACT A LONG FROM SRC (2 pixels)
		move.b	d0,d3						;pick up blue component as a byte
		and.b	#$1f,d3
		lsr.l	#5,d0						;toss blue
		move.b	d0,d2						;pick up green component as a byte
		and.b	#$1f,d2
		lsr.l	#5,d0						;toss green
		move.b	d0,d1						;pick up red component as a word
		and.b	#$1f,d1
		add.w	d1,(a1)+					;accumulate red value
		add.w	d2,(a1)+					;accumulate green value
		add.w	d3,(a1)+					;accumulate blue value
;
; Do second pixel in long
;
		lsr.l	#5+1,d0						;move to second 16-bit pixel in long
		move.b	d0,d3						;pick up blue component as a byte
		and.b	#$1f,d3
		lsr.l	#5,d0						;toss blue
		move.b	d0,d2						;pick up green component as a byte
		and.b	#$1f,d2
		lsr.l	#5,d0						;toss green
		move.b	d0,d1						;pick up red component as a word
		and.b	#$1f,d1
		add.w	d1,(a1)+					;accumulate red value
		add.w	d2,(a1)+					;accumulate green value
		add.w	d3,(a1)+					;accumulate blue value

		dbra	d5,@NDLONG					;repeat for all longs

;		add.l	a5,a3						;bump source to next row
		_pmVersion
		dbra	d7,NextAverageV16	 		;loop while scan lines left

		move.w	(a7)+,d7					;retrieve # scanlines merged (0-based)
		addq	#1,d7						;make it 1 based

; Now we must compute the average of the accumulated R-G-B's

		move.l	a2,a1						;point to destination buffer
		move.l	AvrgBuf(A6),A0				;point to accumulation buffer
		move	d4,d3						;longs in source
;
; if it's a deep mask, we promote all 16-bit values to 32-bit
;
		move.w	maskshift(a6),d0
		cmp.w	#4,d0
		bge		Promote16Loop

		cmp.w	#2,d7						;two scan lines merged?
		beq.s	@useShift					;avoid division by using a shift

@hardWay
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up red accumulation
		divu.w	d7,d1						;get red average (alpha channel [bit 6] should be clear)
		move.w	d1,d0						;put in low byte of pixel (only 6 bits count)

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up green accumulation
		divu.w	d7,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up blue accumulation
		divu.w	d7,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

;
; Now do second pixel in long
;
		lsl.l	#5+1,d0						;bump to beginning of second pixel
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up red accumulation
		divu.w	d7,d1						;get red average (alpha channel [bit 6] should be clear)
		or.w	d1,d0						;put in low byte of pixel (only 5 bits count)

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up green accumulation
		divu.w	d7,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up blue accumulation
		divu.w	d7,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

		swap	d0							;pixels mixed in AvrgBuf because of how constructed
		move.l	d0,(a1)+					;dump pixel into srcBuf
		dbra	d3,@hardWay					;loop for all src longs
		rts

@useShift
		move.w	(a0)+,d1					;pick up red accumulation
		lsr.b	#1,d1						;get red average
		move.w	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up green accumulation
		lsr.b	#1,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up blue accumulation
		lsr.b	#1,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel
;
; do second pixel (2/long in 16-bit mode)
;
		lsl.l	#5+1,d0
		move.w	(a0)+,d1					;pick up red accumulation
		lsr.b	#1,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up green accumulation
		lsr.b	#1,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up blue accumulation
		lsr.b	#1,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

		swap	d0
		move.l	d0,(a1)+					;dump pixel into srcBuf
		dbra	d3,@useShift				;loop for all src longs
		rts

Promote16Loop
;
; Average 16 bit values and put result back in AvrgBuf, then call
; Scale16to32 to promote to 32 bits
;
		move.l	a0,a1						;copy AvrgBuf ptr
		cmp.w	#2,d7						;two scan lines merged?
		beq.s	@useShift					;avoid division by using a shift

@hardWay
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up red accumulation
		divu.w	d7,d1						;get red average (alpha channel [bit 6] should be clear)
		move.w	d1,d0						;put in low byte of pixel (only 6 bits count)

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up green accumulation
		divu.w	d7,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up blue accumulation
		divu.w	d7,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

;
; Now do second pixel in long
;
		lsl.l	#5+1,d0						;bump to beginning of second pixel
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up red accumulation
		divu.w	d7,d1						;get red average (alpha channel [bit 6] should be clear)
		or.w	d1,d0						;put in low byte of pixel (only 5 bits count)

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up green accumulation
		divu.w	d7,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		moveq	#0,d1						;use for extending to word data
		move.w	(a0)+,d1					;pick up blue accumulation
		divu.w	d7,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

		swap	d0							;pixels mixed in AvrgBuf because of how constructed
		move.l	d0,(a1)+					;dump pixel into srcBuf
		dbra	d3,@hardWay					;loop for all src longs
		bra.s	@DoPromote

@useShift
		move.w	(a0)+,d1					;pick up red accumulation
		lsr.b	#1,d1						;get red average
		move.w	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up green accumulation
		lsr.b	#1,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up blue accumulation
		lsr.b	#1,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel
;
; do second pixel (2/long in 16-bit mode)
;
		lsl.l	#5+1,d0
		move.w	(a0)+,d1					;pick up red accumulation
		lsr.b	#1,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up green accumulation
		lsr.b	#1,d1						;get green average
		or.b	d1,d0						;put in low byte of pixel

		lsl.l	#5,d0						;make room for next component
		move.w	(a0)+,d1					;pick up blue accumulation
		lsr.b	#1,d1						;get red average
		or.b	d1,d0						;put in low byte of pixel

		swap	d0
		move.l	d0,(a1)+					;dump pixel into srcBuf
		dbra	d3,@useShift				;loop for all src longs
@DoPromote
;
; Call Scale16to32 to promote pixels to 32 bpp
;
		move.l	AvrgBuf(A6),A0				;pointer to source
		move.l	a2,a1						;pointer to destination
		lsl.l	#3,d4						;calc size of dst: 
											;longs to bytes and 16 bit to 32 bit = *8 <7JULY90 KON>
		add.l	d4,a2						;calc end of dst buffer
		jmp		Scale16to32					;inherits return address.

;
;----------------Bottom of 16-bit average loop ----------------
;
;*********************************************************************

	ALIGN 	Alignment

;*********************************************************************
;
;	Loop to expand and merge D7 1-bit/pixel scanlines.
;
;ENTRY:
;	D0:	scratch						A0: scratch ptr
;	D1: scratch						A1: scratch ptr
;	D2: scratch						A2: destination
;	D3: scratch						A3: source
;	D4: src longs					A4:	src pmtable 								A5:	rowbytes
;	D5:	srcAlign					A5:	rowbytes
;	D6:	realDepth (pixel size)
;	D7:	Scanline Count (zero based)
;
;EXIT:
;
;	a3: new srcaddr
;
;GLOBALS:	AvgBufPtr(a6), AvgBufSize(a6)
;
;*********************************************************************

ONEDEEP

; LOOP FOR ALL LONGS IN SRC SCANLINE

		move.l	a3,a0						;point to source
		move.l	a2,a1						;point to destination
		move	d4,d1 						;get count of longs

@Align	bfextu	(a0){d5:0},d0				;get an aligned long of source
		add		#4,a0						;bump to next long
		move.l	d0,(a1)+					;put a long to destination
		dbra	d1,@Align					;loop for all longs

;		add.l	a5,a3						;bump source to next row
		_pmVersion
		dbra	d7,@OneMerge				;						<KON 1NOV90>
		rts
@OneMerge

		move.l	a3,a0						;point to source
		move.l	a2,a1						;point to destination
		move	d4,d1 						;get count of longs
@NXTLNG	bfextu	(a0){d5:0},d0				;get an aligned long of source
		add		#4,a0						;bump to next long
		or.l	d0,(a1)+					;put a long to destination
		dbra	d1,@NXTLNG					;loop for all longs				<10July90 KON>

;		add.l	a5,a3						;bump source to next row
		_pmVersion
		dbra	d7,@OneMerge
		rts

;******************************************************************************************

;---------------------------------------------------------------;
;																;
;  INTERFACE TO EACH OF THE STRETCHBITS SCANLINE LOOPS: 		;
;																;
;  REGISTERS:	A0: 			D0: CLOBBERED					;
;				A1: 			D1: CLOBBERED					;
;				A2: MASKPTR 	D2: LONGCNT 					;
;				A3: SRCPTR		D3: FGCOLOR						;
;				A4: DSTPTR		D4: BKCOLOR						;
;				A5: 			D5: CLOBBERED					;
;				A6: 			D6: DSTALIGN					;
;				A7: 			D7: INVERTFLAG						;
;																;
;---------------------------------------------------------------;

	ALIGN 	Alignment

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb
;-------------------------------------------------------
;
;  MODE 0 OR 4: SRC --> DST
;
;  FOR PROPER INVERSION, ASSUME SRC IS COLORED.  INVERT SRC AFTER
;  ADDING COLOR TO IT (RATHER THAN EXCHANGING FG AND BK, INVERT THEM).

;
; On first entry, find fastest drawing case, and put it in ModeCase(a6)
;
stMask0	TST.B	alphaMode(A6)				;drawing in alpha mode?				<42>
		BEQ.S	@1							;no, use normal loops				<42>
		LEA		stAlphaMask0,A0				;get address of alpha copy loop		<42>
		BRA.S	@RememberAndDoIt			;go remember and do it				<42>
	@1:	lea		FaststMask0,a0				;assume fast
;
; should we colorize here?
;
		btst	#ColorizeInModeCaseBit,XLateFlag(a6)
		bne.s	@goslow
;
;if we got here, there's no colorizing
;
@DontColorize
		tst.l	d6				;need to shift?
		bne.s	@ShiftNoColor
		tst.l	d7				;need to invert?
		bne.s	@ShiftNoColor
;
;if we got here, it's the fast case

@RememberAndDoIt
		move.l	a0,ModeCase(a6)
		jmp		(a0)
@goSlow
		lea		stMask0Slow,a0						;shift, invert, and colorize
		bra.s	@RememberAndDoIt

@ShiftNoColor
		lea		stMask0ShiftNoColorInvert,a0		;shift, don't colorize, but invert
		bra.s	@RememberAndDoIt
;
; Copy through alpha mask	<42>
;
stAlphaMask0
		MOVE.L	alphaMask(A6),D5
	@1:	BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		MOVE.L	(A4),D1			;GET DST DATA
		EOR.L	D1,D0			;apply src to dst
		AND.L	(A2)+,D0		;clip with mask
		AND.L	D5,D0			;clip with alpha mask
		EOR.L	D1,D0			;reapply src
		MOVE.L	D0,(A4)+		;PUT RESULT IN DST
		DBRA	D2,@1			;LOOP ALL LONGS THIS ROW
		EOR.L	D4,D3			;(THIS MAY NOT BE NEEDED)
		BRA 	NEXTDST 		;GO FOR NEXT ROW

;
;don't shift, invert, or colorize
;
FaststMask0
;draw
		move.l	(a3)+,d0		;get source
		move.l	(a4),d1			;get dst
		eor.l	d1,d0			;src xor dst
		move.l	(a2)+,d3
		and.l	d3,d0			;(src xor dst) and mask
		eor.l	d0,d1
		move.l	d1,(a4)+		;dst = [(src xor dst) and mask] xor dst
		DBRA	D2,FaststMask0	;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;GO FOR NEXT ROW
;
; shift, no colorize, and invert
;
stMask0ShiftNoColorInvert
;shift
		BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		move.l	(a2)+,d3
;invert
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
;draw
		move.l	(a4),d1			;get dst
		eor.l	d1,d0			;src xor dst
		and.l	d3,d0			;(src xor dst) and mask
		eor.l	d0,d1			;dst = [(src xor dst) and mask] xor dst
		move.l	d1,(a4)+
		DBRA	D2,stMask0ShiftNoColorInvert	;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;GO FOR NEXT ROW

	if 0 then
; shift, colorize, and invert
stMask0Slow
;shift
		BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		move.l	(a2)+,d3		;get mask
;invert
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
;colorize
		MOVE.L	D0,D5			;COPY SRC
		AND.L	D3,D0			;ADD FG COLOR TO SRC
		move.l	(a4),d1			;get dst here to help pipelining
		NOT.L	D5				;GET NOT SRC
		AND.L	D4,D5			;ADD BK COLOR TO NOT SRC
		OR.L	D5,D0			;COMBINE FG/BK DATA
;draw
		eor.l	d1,d0			;src xor dst
		and.l	d3,d0			;(src xor dst) and mask
		eor.l	d0,d1			;dst = [(src xor dst) and mask] xor dst
		move.l	d1,(a4)+
		DBRA	D2,stMASK0Slow	;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;GO FOR NEXT ROW
	else

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

stMASK0Slow
;-------------------------------------------------------
;
;  MODE 0 OR 4: SRC --> DST
;
;  FOR PROPER INVERSION, ASSUME SRC IS COLORED.  INVERT SRC AFTER
;  ADDING COLOR TO IT (RATHER THAN EXCHANGING FG AND BK, INVERT THEM).
;
		BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		MOVE.L	(A2)+,D1		;GET MASK
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET

		MOVE.L	D0,D5			;COPY SRC
		AND.L	D3,D0			;ADD FG COLOR TO SRC
		NOT.L	D5				;GET NOT SRC
		AND.L	D4,D5			;ADD BK COLOR TO NOT SRC
		OR.L	D5,D0			;COMBINE FG/BK DATA
		AND.L	D1,D0			;MASK RESULT

		NOT.L	D1				;FORM NOTMASK
		AND.L	(A4),D1 		;GET DST DATA
		OR.L	D1,D0			;MERGE WITH SRC DATA
		MOVE.L	D0,(A4)+		;PUT RESULT IN DST
		DBRA	D2,stMASK0Slow	;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;GO FOR NEXT ROW
	endif

	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 1 OR 5: SRC OR DST --> DST
;
;  ASSUME SRC IS EXPANDED BLACK/WHITE PATTERN.  SRC IS USED
;  TO PUNCH DST, FG APPLIED TO SRC, THEN COMBINED WITH DST.
;
stMASK1	BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		MOVE.L	(A2)+,D1		;GET MASK

		AND.L	D1,D0			;MASK SRC
		MOVE.L	D0,D1			;COPY MASKED SRC
		AND.L	D3,D1			;ADD FG COLOR TO SRC

		NOT.L	D0				;GET NOT MASKED SRC
		AND.L	(A4),D0			;USE TO PUNCH OUT DST
		OR.L	D1,D0			;COMBINE SRC AND DST

		MOVE.L	D0,(A4)+		;PUT RESULT TO DST
		DBRA	D2,stMASK1		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 2 OR 6: SRC XOR DST --> DST
;
stMASK2	BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		AND.L	(A2)+,D0		;AND WITH MASK
		EOR.L	D0,(A4)+		;XOR RESULT INTO DST
		DBRA	D2,stMASK2		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 3 OR 7: SRC BIC DST --> DST
;
;  ASSUME SRC IS EXPANDED BLACK/WHITE PATTERN.  SRC IS USED
;  TO PUNCH DST, BK APPLIED TO SRC, THEN COMBINED WITH DST.
;
stMASK3
	if 0 then
		lea		stMASK3NoColorize,a0		;assume no colorizing
;
; should we colorize here?
;
		btst	#ColorizeInModeCaseBit,XLateFlag(a6)
		bne.s	@goslow

@RememberAndDoIt
		move.l	a0,ModeCase(a6)
		jmp		(a0)
@goSlow
		lea		stMASK3Colorize,a0				;shift, invert, and colorize
		bra.s	@RememberAndDoIt
	endif

stMASK3Colorize
		BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		MOVE.L	(A2)+,D1		;GET MASK

		AND.L	D1,D0			;MASK SRC
		MOVE.L	D0,D1			;COPY MASKED SRC
		AND.L	D4,D1			;AND SRC WITH BG COLOR (FOR BIC)

		NOT.L	D0				;GET BITS THAT AREN'T BIC'ED
		AND.L	(A4),D0			;GET DST THAT DOESN'T CHANGE
		OR.L	D1,D0			;FORM SRC BIC DST

		MOVE.L	D0,(A4)+		;AND PUT TO DST
		DBRA	D2,stMASK3Colorize		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW

	if 0 then
stMASK3NoColorize
		BFEXTU	(A3){D6:0},D0	;get an aligned long from bitmap
		ADD		#4,A3			;bump to next long of source
		EOR.L	D7,D0			;INVERT SRC IF MODE BIT 2 SET
		MOVE.L	(A2)+,D1		;GET MASK

		AND.L	D1,D0			;MASK SRC
		MOVE.L	D0,D1			;COPY MASKED SRC

		NOT.L	D0				;GET BITS THAT AREN'T BIC'ED
		AND.L	(A4),D0			;GET DST THAT DOESN'T CHANGE
		OR.L	D1,D0			;FORM SRC BIC DST

		MOVE.L	D0,(A4)+		;AND PUT TO DST
		DBRA	D2,stMASK3NoColorize		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW
	endif

; note that arithmetic modes expect the destination pixel size instead of the invert state in D7

	ALIGN 	Alignment

stAddOver
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		LEA		red(A5,D0*8),A0		;figure out where it lives in the color table
		BFEXTU	(A4){D3:D7},D0		;a pixel of the destination
		LEA		red(A5,D0*8),A1		;figure out where destination lives
		MOVE	(A0)+,D0			;red	get source color value
		ADD		(A1)+,D0			;		combine source and destination
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A0)+,D0			;green	get source color value
		ADD		(A1)+,D0			;		combine source and destination
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A0)+,D0			;blue	get source color value
		ADD		(A1)+,D0			;		combine source and destination
		ASL.L	D5,D0				;		save the top bits in the top word
		SWAP	D0					;r, g, b in high word
		MOVE.B	([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW


	ALIGN 	Alignment

stAddPin
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		LEA		red(A5,D0*8),A0		;figure out where it lives in the color table
		BFEXTU	(A4){D3:D7},D0		;a pixel of the destination
		LEA		red(A5,D0*8),A1		;figure out where destination lives
		MOVE	(A0)+,D0			;red	get source color value
		ADD		(A1)+,D0			;		combine source and destination
		BCS.S	@tooBigRed
		CMP		pin+4(A6),D0		;		bigger than pin value?
		BLS.S	@notTooBigRed		;		no, no problem
@tooBigRed
		MOVE	pin+4(A6),D0
@notTooBigRed
		ASL.L	D5,D0				;save the top bits in the top word
		MOVE	(A0)+,D0			;green	get source color value
		ADD		(A1)+,D0			;		combine source and destination
		BCS.S	@tooBigGreen
		CMP		pin+2(A6),D0		;		bigger than pin value?
		BLS.S	@notTooBigGreen		;		no, no problem
@tooBigGreen
		MOVE	pin+2(A6),D0
@notTooBigGreen
		ASL.L	D5,D0				;save the top bits in the top word
		MOVE	(A0)+,D0			;blue	get source color value
		ADD		(A1)+,D0			;		combine source and destination
		BCS.S	@tooBigBlue
		CMP		pin(A6),D0			;		bigger than pin value?
		BLS.S	@notTooBigBlue		;		no, no problem
@tooBigBlue
		MOVE	pin(A6),D0
@notTooBigBlue
		ASL.L	D5,D0				;save the top bits in the top word
		SWAP	D0					;r, g, b in high word
		MOVE.B	([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW


	ALIGN 	Alignment

stSubOver
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		LEA		red(A5,D0*8),A0		;figure out where it lives in the color table
		BFEXTU	(A4){D3:D7},D0		;a pixel of the destination
		LEA		red(A5,D0*8),A1		;figure out where destination lives
		MOVE	(A1)+,D0			;red	get destination color value
		SUB		(A0)+,D0			;		less source
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A1)+,D0			;green	get destination color value
		SUB		(A0)+,D0			;		less source
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A1)+,D0			;blue	get destination color value
		SUB		(A0)+,D0			;		less source
		ASL.L	D5,D0				;		save the top bits in the top word
		SWAP	D0					;r, g, b in high word
		MOVE.B	([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW


	ALIGN 	Alignment

stSubPin
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		LEA		red(A5,D0*8),A0		;figure out where it lives in the color table
		BFEXTU	(A4){D3:D7},D0		;a pixel of the destination
		LEA		red(A5,D0*8),A1		;figure out where destination lives
		MOVE	(A1)+,D0			;red	get destination color value
		SUB		(A0)+,D0			;		less source
		BCS.S	@tooSmallRed
		CMP		pin+4(A6),D0		;		smaller than pin value?
		BHS.S	@notTooSmallRed		;		no, no problem
@tooSmallRed
		MOVE	pin+4(A6),D0
@notTooSmallRed
		ASL.L	D5,D0				;save the top bits in the top word
		MOVE	(A1)+,D0			;green	get destination color value
		SUB		(A0)+,D0			;		less source
		BCS.S	@tooSmallGreen
		CMP		pin+2(A6),D0		;		smaller than pin value?
		BHS.S	@notTooSmallGreen	;		no, no problem
@tooSmallGreen
		MOVE	pin+2(A6),D0
@notTooSmallGreen
		ASL.L	D5,D0				;save the top bits in the top word
		MOVE	(A1)+,D0			;blue	get destination color value
		SUB		(A0)+,D0			;		less source
		BCS.S	@tooSmallBlue
		CMP		pin(A6),D0			;		smaller than pin value?
		BHS.S	@notTooSmallBlue	;		no, no problem
@tooSmallBlue
		MOVE	pin(A6),D0
@notTooSmallBlue
		ASL.L	D5,D0				;save the top bits in the top word
		SWAP	D0					;r, g, b in high word
		MOVE.B	([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW


	ALIGN 	Alignment

stMax
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		LEA		red(A5,D0*8),A0		;figure out where it lives in the color table
		BFEXTU	(A4){D3:D7},D0		;a pixel of the destination
		LEA		red(A5,D0*8),A1		;figure out where destination lives
		MOVE	(A0)+,D0			;red	get source color value
		CMP		(A1),D0				;		compare source and destination
		BHS.S	@gotTheMaxRed
		MOVE	(A1),D0
@gotTheMaxRed
		ADDQ	#2,A1
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A0)+,D0			;green	get source color value
		CMP		(A1),D0				;		compare source and destination
		BHS.S	@gotTheMaxGreen
		MOVE	(A1),D0
@gotTheMaxGreen
		ADDQ	#2,A1
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A0)+,D0			;blue	get source color value
		CMP		(A1),D0				;		compare source and destination
		BHS.S	@gotTheMaxBlue
		MOVE	(A1),D0
@gotTheMaxBlue
		ASL.L	D5,D0				;		save the top bits in the top word
		SWAP	D0					;r, g, b in high word
		MOVE.B	([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW


	ALIGN 	Alignment

stMin
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		LEA		red(A5,D0*8),A0		;figure out where it lives in the color table
		BFEXTU	(A4){D3:D7},D0		;a pixel of the destination
		LEA		red(A5,D0*8),A1		;figure out where destination lives
		MOVE	(A0)+,D0			;red	get source color value
		CMP		(A1),D0				;		compare source and destination
		BLS.S	@gotTheMinRed
		MOVE	(A1),D0
@gotTheMinRed
		ADDQ	#2,A1
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A0)+,D0			;green	get source color value
		CMP		(A1),D0				;		compare source and destination
		BLS.S	@gotTheMinGreen
		MOVE	(A1),D0
@gotTheMinGreen
		ADDQ	#2,A1
		ASL.L	D5,D0				;		save the top bits in the top word
		MOVE	(A0)+,D0			;blue	get source color value
		CMP		(A1),D0				;		compare source and destination
		BLS.S	@gotTheMinBlue
		MOVE	(A1),D0
@gotTheMinBlue
		ASL.L	D5,D0				;		save the top bits in the top word
		SWAP	D0					;r, g, b in high word
		MOVE.B	([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW


	ALIGN 	Alignment

stAvg
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		LEA		red(A5,D0*8),A0		;figure out where it lives in the color table
		BFEXTU	(A4){D3:D7},D0		;a pixel of the destination
		LEA		red(A5,D0*8),A1		;figure out where destination lives
		MOVEQ	#2,D1				;do three times
		MOVE	invSize(A6),D5 		;do once for r, b and g
		ADD		D5,D5				;initialize at 2x for shift count
		CLR		-(SP)				;make space & initialize average r, b, g
@nextColor
		MOVE	(A0)+,D0			;get source color value
		MULU	(weight,A6,D1*2),D0 ;weight varies from 0 to 1
		MOVE	(A1)+,D4			;get destination value
		MULU	(notWeight,A6,D1*2),D4 ;weight varies from 1 to 0
		ADD.L	D4,D0				;combine them
		SWAP	D0					;high word is interesting part
		MOVE	rtShift(A6),D4		;amount to shift right
		LSR		D4,D0				;get top bits only
		LSL		D5,D0				;shift by 2x, 1x, or 0 (for r, g, & b)
		OR		D0,(SP)				;combine r, g, b
		SUB		invSize(A6),D5 		;decrement shift, weight index
		DBRA	D1,@nextColor		;do for b & g as well

		MOVE	(SP)+,D0			;r, g, b
		MOVE.B	([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW


	ALIGN 	Alignment

stTransparent
@loopTop
		ADD.L	D7,D6				;bump source pointer
@loopTop1
		BFEXTU	(A3){D6:0},D0		;get a long from the source
		CMP.L	D0,D4				;same as the background?
		BEQ.S	@skipLong
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		CMP.L	D0,A5				;same as a pixel of the background?
		BEQ.S	@skip
		BFINS	D0,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW
@skipLong
		ADDQ	#4,A3				;bump the source by a long
		ADD		#32,D3				;bump mask and destination
		SUB		D5,D2				;a longÕs worth of pixels
		BGE.S	@loopTop1
		MOVE.L	bColor(A6),D4		;set up colorMap backcolor for skipping coloring source
		BRA		NEXTDST


	ALIGN 	Alignment

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

stHilite
		BFEXTU	D4{0:D7},D4			;set up a pixel of the backcolor
		BFEXTU	hilitColor(A6){0:D7},D5 ;and a pixel of the hilite color as well
@loopTop
		ADD.L	D7,D6				;bump source pointer
		BFEXTU	(A2){D3:D7},D0		;get a pixel of mask
		BEQ.S	@skip				;if none, skip the pixel
		BFEXTU	(A3){D6:D7},D0		;get a pixel from bitmap
		CMP.L	D4,D0				;is pixel same as background color?			<45>
		BEQ.S	@skip
		BFEXTU	(A4){D3:D7},D0		;get a pixel of the destination
		CMP.L	D4,D0				;same as the background color?
		BNE.S	@tryNew
		BFINS	D5,(A4){D3:D7}
		BRA.S	@skip
@tryNew
		CMP.L	D5,D0				;same as new color?
		BNE.S	@skip
		BFINS	D4,(A4){D3:D7}		;move to the destination
@skip
		ADD.L	D7,D3				;advance to next destination
		DBRA	D2,@loopTop			;LOOP ALL pixels THIS ROW
		BRA 	NEXTDST 			;LOOP FOR NEXT ROW



; all of these loops are as seen in QDciPatchROM.a						<sm 6/9/92>stb
;--------------------------------------------------------------------------
;
;
;	Here begins the arithmetic transfer loops for 32 bits/pixel:
;
;
;
;--------------------------------------------------------------------------
;
;  MODE 42: PAT + DST --> DST (no pin)
;-------------------------------------------------------
;		a0 = hi bit mask	d0 = hi bit clring mask
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = src msb's
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = dst msb's
;-------------------------------------------------------
	ALIGN 	Alignment

stAddOver32
		BSR		arithSetup32	;set up registers for slab bitblt

		move.l	#~$ff808080,d0	;get high bit clearing mask
		move.l	#$00808080,a0	;get high bit mask

@blit	tst.l	(a2)+			;a pixel of the clip region
		beq.s	@skip

		move.l	0(a3,d6),d1		;get src pixel
		move.l	a0,d7			;copy high bit mask
		and.l	d1,d7			;remember src msb's
		and.l	d0,d1			;mask out stragglers

		move.l	(a1),d5			;get dest pixel
		move.l	a0,d3			;copy high bit mask
		and.l	d5,d3			;remember dst msb's
		and.l	d0,d5			;mask out stragglers

		add.l	d1,d5			;merge src with dst
		eor.l	d7,d3			;compute partial sum of msb's
		eor.l	d3,d5			;compute partial sum of msb's
		MOVE.L	d5,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Utility arithSetup
; sets up registers for 32 bit arithmetic modes:
;
;  INPUT
;  REGISTERS:	A0: 			D0: CLOBBERED					;
;				A1: 			D1: CLOBBERED					;
;				A2: MASKPTR 	D2: LONGCNT 					;
;				A3: SRCPTR		D3: FGCOLOR						;
;				A4: DSTPTR		D4: BKCOLOR						;
;				A5: 			D5: CLOBBERED					;
;				A6: 			D6: DSTALIGN					;
;				A7: 			D7: PixelSize					;
;																;

arithSetup32
		move.l	a4,a1			;reroute dstPtr
		moveq	#0,D6			;zero src index
	;	moveq	#-1,D4			;flush src modulus
	;	move.l	d4,patHMask(a6)
		RTS

	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 41: PAT + DST --> DST (pin to max)
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = lo3Bytes mask
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = pin pixel 0rgb
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = src pixel
;-------------------------------------------------------
stAddPin32
		BSR		arithSetup32	;set up registers for slab bitblt

		;set up pin pixel as 0rgb in D3

		moveq	#0,d3			;start fresh, waste iTabRes
		move.b	pin+4(a6),d3	;pick up red
		swap	d3				;put in byte 3
		move.w	pin+2(a6),d3	;get green in byte 2
		move.b	pin(a6),d3		;put blue in lo byte

		move.l	Lo3Bytes,d1		;pick up mask

@blit	tst.l	(a2)+			;a pixel of the clip region
		beq.s	@skip

		move.l	0(a3,d6),d7		;get src pixel
		and.l	d1,d7			;waste high byte
		move.l	d7,d0			;make a copy of the src xrgb

		move.l	(a1),d5			;get dest pixel
		and.l	d1,d5			;waste high byte

		clr.b	d0				;prevent carries from below
		add.w	d5,d0			;add green components
		BCS.S	@PinGreen
		cmp.w	d3,d0			;do we need to pin result?
		bls.s	@GreenOK
@PinGreen
		move.w	d3,d0			;use pin value instead
@GreenOK
		move.b	d7,d0			;get src blue
		add.b	d5,d0			;add dest blue
		BCS.S	@PinBlue
		cmp.b	d3,d0			;do we need to pin result?
		bls.s	@BlueOK
@PinBlue
		move.b	d3,d0			;use pin value instead
@BlueOK
		clr.w	d5				;now d5 has only red in byte 3
		add.l	d5,d0			;add red components
		cmp.l	d3,d0			;compare red components
		bls.s	@RedOK
@PinRed
		swap	d3				;get max red in lo word
		swap	d0				;get too big red in lo word
		move.w	d3,d0			;pin to max red
		swap	d0				;get back 0rgb
		swap	d3				;restore pin pixel
@RedOK
		MOVE.L	d0,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 46: DST - PAT --> DST (no pin)
;
;-------------------------------------------------------
;		a0 = 				d0 = hi bit clring mask
;		a1 = dstPtr			d1 = high bit mask
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = src msb's
;		a4 = 				d4 = dst msb's
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = src pixel
;-------------------------------------------------------
stSubOver32
		BSR		arithSetup32	;set up registers for slab bitblt

		move.l	#~$ff808080,d0	;get high bit clearing mask
		move.l	#$00808080,d1	;get high bit mask

@blit	tst.l	(a2)+			;a pixel of the clip region
		beq.s	@skip

		move.l	0(a3,d6),d7		;get src pixel
		move.l	d1,d3			;copy high bit mask
		and.l	d7,d3			;remember src msb's
		eor.l	d1,d3			;invert src msb's
		and.l	d0,d7			;mask out stragglers

		move.l	(a1),d5			;get dest pixel
		move.l	d1,d4			;copy high bit mask
		and.l	d5,d4			;remember dst msb's
		and.l	d0,d5			;mask out high byte
		or.l	d1,d5			;force high bits on

		sub.l	d7,d5			;compute dst - src
		eor.l	d3,d4			;compute partial sum of msb's
		eor.l	d4,d5			;compute partial sum of msb's
		MOVE.L	d5,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	patHMask(a6),d6	;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 43: DST - PAT --> DST (pin to min)
;
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = lo3Bytes mask
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = pin pixel 0rgb
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = src pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = dst pixel
;-------------------------------------------------------
stSubPin32
		BSR		arithSetup32	;set up registers for slab bitblt

		;set up pin pixel as 0rgb in D3

		moveq	#0,d3			;start fresh, waste iTabRes
		move.b	pin+4(a6),d3	;pick up red
		swap	d3				;put in byte 3
		move.w	pin+2(a6),d3	;get green in byte 2
		move.b	pin(a6),d3		;put blue in lo byte

		move.l	Lo3Bytes,d1		;pick up mask

@blit	tst.l	(a2)+			;a pixel of the clip region
		beq.s	@skip
		move.l	0(a3,d6),d5		;get src pixel
		and.l	d1,d5			;waste high byte

		move.l	(a1),d7			;get dest pixel
		and.l	d1,d7			;waste high byte
		move.l	d7,d0			;make a copy of the dst xrgb

		st		d0				;prevent borrows from below
		sub.w	d5,d0			;sub green components
		BCS.S	@PinGreen
		cmp.w	d3,d0			;do we need to pin result?
		bhs.s	@GreenOK
@PinGreen
		move.w	d3,d0			;use pin value instead
@GreenOK
		move.b	d7,d0			;get dest blue
		sub.b	d5,d0			;sub src blue
		BCS.S	@PinBlue
		cmp.b	d3,d0			;do we need to pin result?
		bhs.s	@BlueOK
@PinBlue
		move.b	d3,d0			;use pin value instead
@BlueOK
		clr.w	d5				;now d5 has only red in byte 3
		sub.l	d5,d0			;sub red components
		cmp.l	d3,d0			;compare red components
		bge.s	@RedOK
@PinRed
		swap	d3				;get max red in lo word
		swap	d0				;get too big red in lo word
		move.w	d3,d0			;pin to max red
		swap	d0				;get back 0rgb
		swap	d3				;restore pin pixel
@RedOK

		MOVE.L	d0,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 45: MAX(PAT, DST) --> DST
;
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = 
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
stMax32
		BSR		arithSetup32	;set up registers for slab bitblt

@blit	tst.l	(a2)+			;a pixel of the clip region
		beq.s	@skip
		move.l	0(a3,d6),d1		;get src pixel
		move.l	(a1),d5			;get dest pixel

		move.l	d5,d0			;make a copy of the dest xrgb
		cmp.w	d1,d0			;compare g,b components
		BHI.S	@gotMaxGreen
		move.w	d1,d0			;keep the bigger of the two
		move.b	d5,d0			;prime for blue
@gotMaxGreen
		cmp.b	d1,d5			;compare blue components
		BHI.S	@gotMaxBlue
		move.b	d1,d0			;keep the bigger of the two
@gotMaxBlue
		swap	d1
		swap	d0
		cmp.b	d1,d0			;compare red components
		BHI.S	@gotMaxRed
		move.b	d1,d0			;keep the bigger of the two
@gotMaxRed
		swap	d0				;get new xrgb
		MOVE.L	d0,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 47: MIN(PAT, DST) --> DST
;
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = 
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
stMin32
		BSR		arithSetup32	;set up registers for slab bitblt

@blit	tst.l	(a2)+			;a pixel of the clip region
		beq.s	@skip
		move.l	0(a3,d6),d1		;get src pixel
		move.l	(a1),d5			;get dest pixel

		move.l	d5,d0			;make a copy of the dest xrgb
		cmp.w	d1,d0			;compare g,b components
		BLS.S	@gotMinGreen
		move.w	d1,d0			;keep the smaller of the two
		move.b	d5,d0			;prime for blue
@gotMinGreen
		cmp.b	d1,d5			;compare blue components
		BLS.S	@gotMinBlue
		move.b	d1,d0			;keep the smaller of the two
@gotMinBlue
		swap	d1
		swap	d0
		cmp.b	d1,d0			;compare red components
		BLS.S	@gotMinRed
		move.b	d1,d0			;keep the smaller of the two
@gotMinRed
		swap	d0				;get new xrgb
		MOVE.L	d0,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 40: AVG(SRC, DST, WEIGHT) --> DST
;
;  CLOBBERS:	D0,D3,D2,A1,A2
;				A3,D6 (BUT NOT IN FASTSLAB)
;-------------------------------------------------------
;		a0 = /last dst		d0 = red weight
;		a1 = dstPtr			d1 = blue/grn weight (scanCount)
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = /last src
;		a4 = 				d4 = /last result
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = src pixel
;-------------------------------------------------------
stAvg32
		lea		@stAvg32Slow,a0	;assume, general blend32 from now on
		move.l	a0,modeCase(a6)
		lea 	weight(a6),a0	;point to weights
		move.w	(a0)+,d3
		cmp.w	(a0)+,d3		;is opColor gray?
		bne.s	@stAvg32Slow
		cmp.w	(a0),d3
		bne.s	@stAvg32Slow
		addq	#1,d3			;yes, check for gray values of $8000 or $7fff
		and.w	#$fffe,d3
		cmp.w	#$8000,d3
		bne.s	@stAvg32Slow
		lea		@stAvg32Half,a0	;use fast 50% blend32 from now on
		move.l	a0,modeCase(a6)
		bra		@stAvg32Half

;-------------------------------------------------------
;
;  	General blend case for non 50% gray weights
;
;
@stAvg32Slow
		BSR		arithSetup32	;set up registers for slab bitblt

		lea		weight(a6),a0	;point at blue weight
		move.l	(a0)+,d1		;get blue/green weight
		move.w	(a0),d0			;get red weight

@short0	moveq	#0,d4			;init last result
		move.l	d4,d3			;init last src
		move.l	d4,a0			;init last dst

@blit	tst.l	(A2)+			;a pixel of the clip region
		BEQ.S	@skip
		move.l	0(a3,d6),d7		;get src pixel
		move.l	(a1),d5			;get dest pixel

@short1	cmp.l	d3,d7			;same as last time?
		bne.s	@blue			;no, go do it
		cmp.l	a0,d5			;same as last time?
		beq.s	@again			;yes, go fast

@blue	moveq	#0,d3			;clr out high end
		move.b	d7,d3			;get src blue
		swap	d1				;get blue weight
		mulu.w	d1,d3			;% blue

		moveq	#0,d4			;clr out high end
		move.b	d5,d4			;get dst blue
		neg.w	d1
		mulu.w	d1,d4			;% blue
		neg.w	d1

		add.l	d3,d4			;get 24 bits of dst blue
		swap	d4				;dst blue
		move.w	d4,a0			;a0 has 000B

@grn	move.w	d7,d3			;get src grn
		lsr.w	#8,d3
		swap	d1				;get grn weight
		mulu.w	d1,d3			;% grn

		move.w	d5,d4			;get dst grn
		lsr.w	#8,d4
		neg.w	d1
		mulu.w	d1,d4			;% grn
		neg.w	d1

		add.l	d3,d4			;get 24 bits of dst grn
		swap	d4				;dst grn
		lsl.w	#8,d4
		add.w	d4,a0			;a0 has 00GB

@red	moveq	#0,d3			;clr out high end
		swap	d7
		move.b	d7,d3			;get src red
		mulu.w	d0,d3			;% red

		moveq	#0,d4			;clr out high end
		swap	d5
		move.b	d5,d4			;get dst red
		neg.w	d0
		mulu.w	d0,d4			;% red
		neg.w	d0

		add.l	d3,d4			;get 24 bits of dst red
		move.w	a0,d4			;d4 has 0RGB

@short2	swap	d5				;get back dst
		move.l	d5,a0			;save for short circuit
		swap	d7				;get back src
		move.l	d7,d3			;save for short circuit

@again	MOVE.L	d4,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	patHMask(a6),d6	;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;--------------------------------------------
;
; 	Optimized 50% blend case for 32 bits/pixel
;
;-------------------------------------------------------
;		a0 = low bit mask	d0 = high bit mask
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = lsb's of result
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
@stAvg32Half
		BSR		arithSetup32	;set up registers for slab bitblt

		move.l	#~$ff808080,d0	;get high bit mask
		move.l	#$10101,a0		;get low bit mask

@blit2	tst.l	(A2)+			;a pixel of the clip region
		BEQ.S	@skip2
		move.l	0(a3,d6),d1		;get src pixel

		move.l	a0,d3			;copy low bit mask
		and.l	d1,d3			;remember src lsb's
		lsr.l	#1,d1			;get almost 1/2 of it
		and.l	d0,d1			;mask out stragglers

		move.l	(a1),d5			;get dest pixel
		and.l	d5,d3			;compute carry out of lsb
		lsr.l	#1,d5			;get almost 1/2 of it
		and.l	d0,d5			;mask out stragglers

		add.l	d5,d1			;merge src with dst
		add.l	d3,d1			;propagate carrys
		MOVE.L	d1,(a1)			;write pattern to dest

@skip2	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit2		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;--------------------------------------------
;
; 	Mode: 36 Transparent for 32 bits/pixel
;
;-------------------------------------------------------
;		a0 = 				d0 = 
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = 
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = backColor
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
stTransparent32
		BSR		arithSetup32	;set up registers for slab bitblt

		move.l	transColor(A6),D5 ;get a pixel of the transparent color

@blit	tst.l	(A2)+			;a pixel of the clip region
		BEQ.S	@skip
		move.l	0(a3,d6),d1		;get src pixel

		cmp.l	d1,d5			;is src backColor?
		beq.s	@skip			;yes, don't write to dst
		MOVE.L	d1,(a1)			;write pattern to dest

@skip	addq.l	#4,a1			;bump dst ptr
		addq.l	#4,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


;Êall of these loops are as seen in QDciPatchROM.a							<sm 6/9/92>stb
;--------------------------------------------------------------------------
;
;
;	Here begin the arithmetic transfer loops for 16 bits/pixel:
;
;
;
	ALIGN 	Alignment

;--------------------------------------------------------------------------
;
;  MODE 42: PAT + DST --> DST (no pin)
;-------------------------------------------------------
;		a0 = hi bit mask	d0 = hi bit clring mask
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = src msb's
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = dst msb's
;-------------------------------------------------------
stAddOver16
		BSR.s	arithSetup16	;set up registers for slab bitblt

		move.w	#$3def,d0		;get high bit clearing mask
		move.w	#$4210,a0		;get high bit mask

@blit	tst.w	(a2)+			;a pixel of the clip region
		beq.s	@skip

		move.w	0(a3,d6),d1		;get src pixel
		move.w	a0,d7			;copy high bit mask
		and.w	d1,d7			;remember src msb's
		and.w	d0,d1			;mask out stragglers

		move.w	(a1),d5			;get dest pixel
		move.w	a0,d3			;copy high bit mask
		and.w	d5,d3			;remember dst msb's
		and.w	d0,d5			;mask out stragglers

		add.w	d1,d5			;merge src with dst
		eor.w	d7,d3			;compute partial sum of msb's
		eor.w	d3,d5			;compute partial sum of msb's
		MOVE.w	d5,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW



	ALIGN 	Alignment

;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Utility arithSetup
; sets up registers for 16 bit arithmetic modes:
;
;  INPUT
;  REGISTERS:	A0: 			D0: CLOBBERED					;
;				A1: 			D1: CLOBBERED					;
;				A2: MASKPTR 	D2: LONGCNT 					;
;				A3: SRCPTR		D3: FGCOLOR						;
;				A4: DSTPTR		D4: BKCOLOR						;
;				A5: 			D5: CLOBBERED					;
;				A6: 			D6: DSTALIGN					;
;				A7: 			D7: PixelSize					;
;																;

arithSetup16
		move.l	a4,a1			;reroute dstPtr
		moveq	#0,D6			;zero src index
	;	moveq	#-1,D4			;flush src modulus
	;	move.l	d4,patHMask(a6)
		tst		dstAlign(a6)	;on longword boundary?
		beq.s	@srcOK
		subq	#2,a3			;align src with mask
@srcOK	RTS


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 41: PAT + DST --> DST (pin to max)
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = 
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = pin pixel 0rgb
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = src pixel
;-------------------------------------------------------
stAddPin16
		BSR.s		arithSetup16	;set up registers for slab bitblt

		;set up pin pixel as 0rgb in D3

		moveq	#0,d3			;start fresh, waste iTabRes
		move.b	pin+4(a6),d3	;pick up red
		lsr.b	#3,d3			;get right aligned 5 bits
		swap	d3				;put in byte 3
		move.w	pin+2(a6),d3	;get green in byte 2
		lsr.w	#3,d3			;get right aligned 5 bits
		move.b	pin(a6),d3		;put blue in lo byte
		lsr.b	#3,d3			;right flush blue

@blit	tst.w	(a2)+			;a pixel of the clip region
		beq.s	@skip

		moveq	#0,d7
		move.w	0(a3,d6),d7		;get src pixel
		add.w	d7,d7			;waste high bit
		lsl.l	#5,d7			;but red in byte 3
		lsr.w	#3,d7			;but green in byte 2, blue in lo byte
		lsr.b	#3,d7			;right flush blue

		moveq	#0,d5
		move.w	(a1),d5			;get dest pixel
		add.w	d5,d5			;waste high bit
		lsl.l	#5,d5			;but red in byte 3
		lsr.w	#3,d5			;but green in byte 2, blue in lo byte
		lsr.b	#3,d5			;right flush blue

		add.l	d5,d7			;add all components at once
		move.l	d7,d0			;prime result with red
		cmp.l	d3,d0			;do we need to pin result?
		bls.s	@redOK			;no, don't pin
		move.l	d3,d0			;use pin value instead
@redOK
		move.w	d7,d0			;prime result with green
		cmp.w	d3,d0			;do we need to pin result?
		bls.s	@greenOK		;no, don't pin
		move.w	d3,d0			;use pin value instead
@greenOK
		move.b	d7,d0			;prime result with blue
		cmp.b	d3,d0			;do we need to pin result?
		bls.s	@blueOK			;no, don't pin
		move.b	d3,d0			;use pin value instead
@blueOK

		lsl.b	#3,d0			;rejoin green/blue
		lsl.w	#3,d0			;rejoin red/green/blue
		lsr.l	#6,d0			;right flush red/green/blue
		MOVE.w	d0,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 46: DST - PAT --> DST (no pin)
;
;-------------------------------------------------------
;		a0 = 				d0 = hi bit clring mask
;		a1 = dstPtr			d1 = high bit mask
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = src msb's
;		a4 = 				d4 = dst msb's
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = src pixel
;-------------------------------------------------------
stSubOver16
		BSR		arithSetup16	;set up registers for slab bitblt

		move.w	#$3def,d0		;get high bit clearing mask
		move.w	#$4210,d1		;get high bit mask

@blit	tst.w	(a2)+			;a pixel of the clip region
		beq.s	@skip

		move.w	0(a3,d6),d7		;get src pixel
		move.w	d1,d3			;copy high bit mask
		and.w	d7,d3			;remember src msb's
		eor.w	d1,d3			;invert src msb's
		and.w	d0,d7			;mask out stragglers

		move.w	(a1),d5			;get dest pixel
		move.w	d1,d4			;copy high bit mask
		and.w	d5,d4			;remember dst msb's
		and.w	d0,d5			;mask out high byte
		or.w	d1,d5			;force high bits on

		sub.w	d7,d5			;compute dst - src
		eor.w	d3,d4			;compute partial sum of msb's
		eor.w	d4,d5			;compute partial sum of msb's
		MOVE.w	d5,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	patHMask(a6),d6	;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 43: DST - PAT --> DST (pin to min)
;
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = lo3Bytes mask
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = pin pixel 0rgb
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = src pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = dst pixel
;-------------------------------------------------------
stSubPin16
		BSR		arithSetup16	;set up registers for slab bitblt

		;set up pin pixel as 0rgb in D3

		moveq	#0,d3			;start fresh, waste iTabRes
		move.b	pin+4(a6),d3	;pick up red
		lsr.b	#3,d3			;get right aligned 5 bits
		swap	d3				;put in byte 3
		move.w	pin+2(a6),d3	;get green in byte 2
		lsr.w	#3,d3			;get right aligned 5 bits
		move.b	pin(a6),d3		;put blue in lo byte
		lsr.b	#3,d3			;right flush blue
		move.l	#$808080,d1		;borrow stopper
		add.l	d1,d3			;prevent borrows from crossing byte boundaries

@blit	tst.w	(a2)+			;a pixel of the clip region
		beq.s	@skip

		moveq	#0,d5
		move.w	0(a3,d6),d5		;get src pixel
		add.w	d5,d5			;waste high bit
		lsl.l	#5,d5			;but red in byte 3
		lsr.w	#3,d5			;but green in byte 2, blue in lo byte
		lsr.b	#3,d5			;right flush blue

		moveq	#0,d7
		move.w	(a1),d7			;get dest pixel
		add.w	d7,d7			;waste high bit
		lsl.l	#5,d7			;but red in byte 3
		lsr.w	#3,d7			;but green in byte 2, blue in lo byte
		lsr.b	#3,d7			;right flush blue
		add.l	d1,d7			;prevent borrows from crossing byte boundaries

		sub.l	d5,d7			;sub all components at once
		move.l	d7,d0			;prime result with red
		cmp.l	d3,d0			;do we need to pin result?
		bhs.s	@redOK			;no, don't pin
		move.l	d3,d0			;use pin value instead
@redOK
		move.w	d7,d0			;prime result with green
		cmp.w	d3,d0			;do we need to pin result?
		bhs.s	@greenOK		;no, don't pin
		move.w	d3,d0			;use pin value instead
@greenOK
		move.b	d7,d0			;prime result with blue
		cmp.b	d3,d0			;do we need to pin result?
		bhs.s	@blueOK			;no, don't pin
		move.b	d3,d0			;use pin value instead
@blueOK

		lsl.b	#3,d0			;rejoin green/blue
		lsl.w	#3,d0			;rejoin red/green/blue
		lsr.l	#6,d0			;right flush red/green/blue
		MOVE.w	d0,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 45: MAX(PAT, DST) --> DST
;
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = 
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
stMax16
		BSR		arithSetup16	;set up registers for slab bitblt

@blit	tst.w	(a2)+			;a pixel of the clip region
		beq.s	@skip

		moveq	#0,d7
		move.w	0(a3,d6),d7		;get src pixel
		add.w	d7,d7			;waste high bit
		lsl.l	#5,d7			;but red in byte 3
		lsr.w	#3,d7			;but green in byte 2, blue in lo byte
		lsr.b	#3,d7			;right flush blue

		moveq	#0,d5
		move.w	(a1),d5			;get dest pixel
		add.w	d5,d5			;waste high bit
		lsl.l	#5,d5			;but red in byte 3
		lsr.w	#3,d5			;but green in byte 2, blue in lo byte
		lsr.b	#3,d5			;right flush blue

		move.l	d7,d0			;prime result with src
		cmp.l	d5,d0			;is dst greater?
		bhs.s	@gotRed			;no, use src
		move.l	d5,d0			;use dst value instead
@gotRed
		move.w	d7,d0			;prime result with src
		cmp.w	d5,d0			;is dst greater?
		bhs.s	@gotGreen		;no, use src
		move.w	d5,d0			;use dst value instead
@gotGreen
		move.b	d7,d0			;prime result with src
		cmp.b	d5,d0			;is dst greater?
		bhs.s	@gotBlue		;no, use src
		move.b	d5,d0			;use dst value instead
@gotBlue

		lsl.b	#3,d0			;rejoin green/blue
		lsl.w	#3,d0			;rejoin red/green/blue
		lsr.l	#6,d0			;right flush red/green/blue
		MOVE.w	d0,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 47: MIN(PAT, DST) --> DST
;
;-------------------------------------------------------
;		a0 = 				d0 = result
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = 
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
stMin16
		BSR		arithSetup16	;set up registers for slab bitblt

@blit	tst.w	(a2)+			;a pixel of the clip region
		beq.s	@skip

		moveq	#0,d7
		move.w	0(a3,d6),d7		;get src pixel
		add.w	d7,d7			;waste high bit
		lsl.l	#5,d7			;but red in byte 3
		lsr.w	#3,d7			;but green in byte 2, blue in lo byte
		lsr.b	#3,d7			;right flush blue

		moveq	#0,d5
		move.w	(a1),d5			;get dest pixel
		add.w	d5,d5			;waste high bit
		lsl.l	#5,d5			;but red in byte 3
		lsr.w	#3,d5			;but green in byte 2, blue in lo byte
		lsr.b	#3,d5			;right flush blue

		move.l	d7,d0			;prime result with src
		cmp.l	d5,d0			;is dst smaller?
		bls.s	@gotRed			;no, use src
		move.l	d5,d0			;use dst value instead
@gotRed
		move.w	d7,d0			;prime result with src
		cmp.w	d5,d0			;is dst smaller?
		bls.s	@gotGreen		;no, use src
		move.w	d5,d0			;use dst value instead
@gotGreen
		move.b	d7,d0			;prime result with src
		cmp.b	d5,d0			;is dst smaller?
		bls.s	@gotBlue		;no, use src
		move.b	d5,d0			;use dst value instead
@gotBlue

		lsl.b	#3,d0			;rejoin green/blue
		lsl.w	#3,d0			;rejoin red/green/blue
		lsr.l	#6,d0			;right flush red/green/blue
		MOVE.w	d0,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;-------------------------------------------------------
;
;  MODE 40: AVG(SRC, DST, WEIGHT) --> DST
;
;  CLOBBERS:	D0,D3,D2,A1,A2
;				A3,D6 (BUT NOT IN FASTSLAB)
;-------------------------------------------------------
;		a0 = /last dst		d0 = red weight
;		a1 = dstPtr			d1 = blue/grn weight (scanCount)
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = /last src
;		a4 = 				d4 = /last result
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = src pixel
;-------------------------------------------------------
stAvg16
		lea		@stAvg16Slow,a0	;assume, general blend16 from now on
		move.l	a0,modeCase(a6)
		lea 	weight(a6),a0	;point to weights
		move.w	(a0)+,d3
		cmp.w	(a0)+,d3		;is opColor gray?
		bne.s	@stAvg16Slow
		cmp.w	(a0),d3
		bne.s	@stAvg16Slow
		addq	#1,d3			;yes, check for gray values of $8000 or $7fff
		and.w	#$fffe,d3
		cmp.w	#$8000,d3
		bne.s	@stAvg16Slow
		lea		@stAvg16Half,a0	;use fast 50% blend16 from now on
		move.l	a0,modeCase(a6)
		bra		@stAvg16Half

;-------------------------------------------------------
;
;  	General blend case for non 50% gray weights
;
;
@stAvg16Slow
		BSR		arithSetup16	;set up registers for slab bitblt

		lea		weight(a6),a0	;point at blue weight
		move.l	(a0)+,d1		;get blue/green weight
		move.w	(a0),d0			;get red weight

@short0	moveq	#0,d4			;init last result
		move.l	d4,d3			;init last src
		move.l	d4,a0			;init last dst

@blit	tst.w	(A2)+			;a pixel of the clip region
		BEQ		@skip
		moveq	#0,d7
		move.w	0(a3,d6),d7		;get src pixel
		moveq	#0,d5
		move.w	(a1),d5			;get dest pixel

@short1	cmp.w	d3,d7			;same as last time?
		bne.s	@hardway		;no, go do it
		cmp.w	a0,d5			;same as last time?
		beq.s	@again			;yes, go fast
@hardway
		add.w	d7,d7			;waste high bit
		lsl.l	#5,d7			;but red in byte 3
		lsr.w	#3,d7			;but green in byte 2, blue in lo byte
		lsr.b	#3,d7			;right flush blue

		add.w	d5,d5			;waste high bit
		lsl.l	#5,d5			;but red in byte 3
		lsr.w	#3,d5			;but green in byte 2, blue in lo byte
		lsr.b	#3,d5			;right flush blue

@blue	moveq	#0,d3			;clr out high end
		move.b	d7,d3			;get src blue
		swap	d1				;get blue weight
		mulu.w	d1,d3			;% blue

		moveq	#0,d4			;clr out high end
		move.b	d5,d4			;get dst blue
		neg.w	d1
		mulu.w	d1,d4			;% blue
		neg.w	d1

		add.l	d3,d4			;get 21 bits of blue
		swap	d4				;right align 5 blue bits
		move.l	d4,a0			;a0 has 000B

@grn	move.w	d7,d3			;get src grn
		lsr.w	#8,d3
		swap	d1				;get grn weight
		mulu.w	d1,d3			;% grn

		move.w	d5,d4			;get dst grn
		lsr.w	#8,d4
		neg.w	d1
		mulu.w	d1,d4			;% grn
		neg.w	d1

		add.l	d3,d4			;get 21 bits of grn
		swap	d4				;right align 5 green bits
		lsl.w	#5,d4			;shift into place
		add.w	d4,a0			;a0 has 00GB

@red	moveq	#0,d3			;clr out high end
		swap	d7
		move.b	d7,d3			;get src red
		mulu.w	d0,d3			;% red

		moveq	#0,d4			;clr out high end
		swap	d5
		move.b	d5,d4			;get dst red
		neg.w	d0
		mulu.w	d0,d4			;% red
		neg.w	d0

		add.l	d3,d4			;get 21 bits of red
		clr.w	d4				;clear lsb's
		lsr.l	#6,d4			;shift into place
		add.w	a0,d4			;d4 has 0RGB

@short2	swap	d5				;get back dst
		lsl.b	#3,d5			;rejoin green/blue
		lsl.w	#3,d5			;rejoin red/green/blue
		lsr.l	#6,d5			;right flush red/green/blue
		move.l	d5,a0			;save for short circuit
		swap	d7				;get back src
		lsl.b	#3,d7			;rejoin green/blue
		lsl.w	#3,d7			;rejoin red/green/blue
		lsr.l	#6,d7			;right flush red/green/blue
		move.l	d7,d3			;save for short circuit

@again	MOVE.w	d4,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	patHMask(a6),d6	;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;--------------------------------------------
;
; 	Optimized 50% blend case for 16 bits/pixel
;
;-------------------------------------------------------
;		a0 = low bit mask	d0 = high bit mask
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = lsb's of result
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = dest pixel
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
@stAvg16Half
		BSR		arithSetup16	;set up registers for slab bitblt

		move.w	#$3def,d0		;get high bit clearing mask
		move.w	#$0421,a0		;get low bit mask

@blit2	tst.w	(A2)+			;a pixel of the clip region
		BEQ.S	@skip2
		move.w	0(a3,d6),d1		;get src pixel

		move.w	a0,d3			;copy low bit mask
		and.w	d1,d3			;remember src lsb's
		lsr.w	#1,d1			;get almost 1/2 of it
		and.w	d0,d1			;mask out stragglers

		move.w	(a1),d5			;get dest pixel
		and.w	d5,d3			;compute carry out of lsb
		lsr.w	#1,d5			;get almost 1/2 of it
		and.w	d0,d5			;mask out stragglers

		add.w	d5,d1			;merge src with dst
		add.w	d3,d1			;propagate carrys
		MOVE.w	d1,(a1)			;write pattern to dest

@skip2	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit2		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW


	ALIGN 	Alignment

;--------------------------------------------
;
; 	Mode: 36 Transparent for 16 bits/pixel
;
;-------------------------------------------------------
;		a0 = 				d0 = 
;		a1 = dstPtr			d1 = src pixel
;		a2 = maskPtr		d2 = run cnt
;		a3 = patPtr			d3 = 
;		a4 = 				d4 = patHMask
;		a5 = 				d5 = backColor
;		a6 = locals			d6 = pattern offset
;		a7 = 				d7 = 
;-------------------------------------------------------
stTransparent16
		BSR		arithSetup16	;set up registers for slab bitblt

		move.l	transColor(A6),D5 ;get a pixel of the transparent color

@blit	tst.w	(A2)+			;a pixel of the clip region
		BEQ.S	@skip
		move.w	0(a3,d6),d1		;get src pixel

		cmp.w	d1,d5			;is src backColor?
		beq.s	@skip			;yes, don't write to dst
		MOVE.w	d1,(a1)			;write pattern to dest

@skip	addq.l	#2,a1			;bump dst ptr
		addq.l	#2,d6			;bump src index
	;	and.w	d4,d6			;constrict to the source long if in a pattern mode
		DBRA	D2,@blit		;LOOP ALL LONGS THIS ROW
		BRA 	NEXTDST 		;LOOP FOR NEXT ROW





	IF	0	THEN
MODETAB DC.W	 MODETAB-MASK0
		DC.W	 MODETAB-MASK1
		DC.W	 MODETAB-MASK2
		DC.W	 MODETAB-MASK3

		DC.W	ModeTab-Avg			;8 AVG(SRC, DST, WEIGHT) --> DST
		DC.W	ModeTab-AddPin		;A SRC + DST --> DST (pin to max)
		DC.W	ModeTab-AddOver		;C SRC + DST --> DST (no pin)
		DC.W	ModeTab-SubPin		;E DST - SRC --> DST (pin to min)
		DC.W	ModeTab-Transparent ;10 SRC less bg --> DST
		DC.W	ModeTab-Max			;12 MAX(SRC, DST) --> DST
		DC.W	ModeTab-SubOver		;14 DST - SRC --> DST (no pin)
		DC.W	ModeTab-Min			;16 MIN(SRC, DST) --> DST
		DC.W	ModeTab-Hilite		;18 src as mask, bg <--> hilite
	ENDIF

	Align	4

stArith16Tab
		DC.L	stAvg16-stArith16Tab			;10 AVG(PAT, DST, WEIGHT) --> DST
		DC.L	stAddPin16-stArith16Tab			;12 PAT + DST --> DST (pin to max)
		DC.L	stAddOver16-stArith16Tab		;13 PAT + DST --> DST (no pin)
		DC.L	stSubPin16-stArith16Tab			;16 DST - PAT --> DST (pin to min)
		DC.L	stTransparent16-stArith16Tab	;18 PAT less bg --> DST
		DC.L	stMax16-stArith16Tab			;1A MAX(PAT, DST) --> DST
		DC.L	stSubOver16-stArith16Tab		;1C DST - PAT --> DST (no pin)
		DC.L	stMin16-stArith16Tab			;1E MIN(PAT, DST) --> DST
		DC.L	stHilite-stArith16Tab			;20 (pat as mask) hilite <--> background

stArith32Tab
		DC.L	stAvg32-stArith32Tab			;10 AVG(PAT, DST, WEIGHT) --> DST
		DC.L	stAddPin32-stArith32Tab			;12 PAT + DST --> DST (pin to max)
		DC.L	stAddOver32-stArith32Tab		;13 PAT + DST --> DST (no pin)
		DC.L	stSubPin32-stArith32Tab			;16 DST - PAT --> DST (pin to min)
		DC.L	stTransparent32-stArith32Tab	;18 PAT less bg --> DST
		DC.L	stMax32-stArith32Tab			;1A MAX(PAT, DST) --> DST
		DC.L	stSubOver32-stArith32Tab		;1C DST - PAT --> DST (no pin)
		DC.L	stMin32-stArith32Tab			;1E MIN(PAT, DST) --> DST
		DC.L	stHilite-stArith32Tab			;20 (pat as mask) hilite <--> background

	ALIGN 	Alignment

SetupStretch
;--------------------------------------------------------------
;
;  Routine to setup case jump for StretchRow,
;  based on horiz numer and denom.
;
;  Call SetupStretch with numer in D0, denom in D1.
;  Returns case jump in A0, fraction in D0.
;
;  Has support for 16-bit stretching (from QDciPatchROM.a)
;
;  Call resulting case jump with:
;
;		A0: srcPtr
;		A1: dstPtr
;		A2: dstLimit
;		D4: fraction
;
;  clobbers D0-D4,A0-A1
;

		MOVE	D3,-(SP)					;SAVE SRC DEPTH

		LEA		DONE,A0			 			;POINT TO ABORT
		TST		D0				 			;IS NUMER <= 0 ?
		BLE		FOUND 			 			;YES, POINT TO ABORT
		TST		D1				 			;IS DENOM <= 0 ?
		BLE		FOUND 			 			;YES, POINT TO ABORT
		LEA		ONE,A0			 			;POINT TO FAST COPY
		CMP		D1,D0 			 			;IS NUMER = DENOM ?
		BEQ		FOUND 			 			;YES, USE FAST COPY
		BLT		SHRNKING			 		;NO, BRANCH IF SHRINKING
;
;  We will be stretching.  Calc fract = denom/numer and check for fast.
;
STRCHING MOVE	  D0,D3 					;MAKE A COPY OF NUMER
		 MOVE	  D1,D4 					;MAKE A COPY OF DENOM
		 CLR.L	  -(SP) 					;ROOM FOR FCN RESULT
		 MOVE	  D1,-(SP)					;PUSH DENOM
		 MOVE	  D0,-(SP)					;PUSH NUMER
		 _FixRatio				 			;CALL FIXRATIO, < 1.0
		 MOVE.L   (SP)+,D0					;POP RESULT

		 LEA	  PIXSTR,A0					;ASSUME WE'RE STRETCHING PIXELS
		 TST	  (SP)						;ARE WE?
		 BNE.S	  FOUND						;=>YES, SRCSHIFT > 0
		 
		 LEA	  DOUBLE,A0 				;CHECK FOR FAST RATIOS
		 CMP	  #$8000,D0
		 BEQ.S	  FOUND
		 LEA	  QUAD,A0
		 CMP	  #$4000,D0
		 BEQ.S	  FOUND
		 LEA	  EIGHT,A0
		 CMP	  #$2000,D0
		 BEQ.S	  FOUND
		 LEA	  SIXTEEN,A0
		 CMP	  #$1000,D0
		 BEQ.S	  FOUND
		 LEA	  THRTWO,A0
		 CMP	  #$0800,D0
		 BEQ.S	  FOUND
		 LEA	  ONE_5,A0
		 CMP	  #$AAAA,D0
		 BEQ.S	  FOUND
		 LEA	  TRIPLE,A0
		 CMP	  #$5555,D0
		 BEQ.S	  FOUND
		 LEA	  SIX,A0
		 CMP	  #$2AAA,D0
		 BEQ.S	  FOUND
;
; check for any multiple of 8:
;
		 EXT.L	  D3						;CLEAR HI WORD OF NUMER
		 DIVU	  D4,D3 					;CALC NUMER DIV DENOM
		 MOVE	  D3,D1 					;SAVE QUOTIENT
		 AND.L	  #$FFFF0007,D3 			;IS SCALE AN EVEN MULT OF 8 ?
		 BNE.S	  NOMATCH					;NO, USE GENERAL STRETCH
		 MOVE	  D1,D0 					;YES RETURN QUOTIENT IN D0
		 LEA	  EIGHTS,A0 				;POINT TO FAST ROUTINE
		 BRA.S	  FOUND			 			;AND RETURN
NOMATCH  LEA	  STRCH,A0					;POINT TO SLOW GENERAL CODE
FOUND	 ADDQ	  #2,SP						;POP SRC SHIFT (IGNORE VALUE)
		 RTS					 			;RETURN WITH CASE JUMP IN A0



;
;  We will be shrinking.  Calc fract = numer/denom and check for fast.
;
SHRNKING 
		CLR.L	-(SP) 						;ROOM FOR FCN RESULT
		MOVE	D0,-(SP)					;PUSH NUMER
		MOVE	D1,-(SP)					;PUSH DENOM
		_FixRatio				 			;CALL FIXRATIO, < 1.0
		MOVE.L	(SP)+,D0					;POP RESULT

		LEA		PIXSHRNK,A0					;ASSUME WE'RE SHRINKING PIXELS
		TST		(SP)						;ARE WE?
		BNE.S	  FOUND						;=>YES, SRCSHIFT > 0

;ciFastRatios		 
		LEA		EIGHTH,A0					;CHECK FOR FAST RATIOS
		CMP		#$2000,D0
		BEQ.S	FOUND
		LEA		QRTR,A0
		CMP		#$4000,D0
		BEQ.S	FOUND
		LEA		HALF,A0
		CMP		#$8000,D0
		BEQ.S	FOUND
		LEA		THREE4,A0
		CMP		#$C000,D0
		BEQ.S	FOUND
		LEA		SHRINK,A0
		BRA		FOUND


	ALIGN 	4

;-----------------------------------------------
;
;  TABLE OF POINTERS TO THE STRETCH ROUTINES
;  USED BY STRETCH AND CCRSRCORE
;
EXTBL	DC.L	ONE-EXTBL				;0
		DC.L	DOUBLE-EXTBL			;4
		DC.L	QUAD-EXTBL				;8
		DC.L	EIGHT-EXTBL				;12
		DC.L	SIXTEEN-EXTBL			;16
		DC.L	THRTWO-EXTBL			;20
		DC.L	BWtoD15-EXTBL			;24
		DC.L	BWtoD24-EXTBL			;28
;
; loops that do colorizing
;
		DC.L	ONEColor-EXTBL			;32
		DC.L	DOUBLEColor-EXTBL
		DC.L	QUADColor-EXTBL
		DC.L	EIGHTColor-EXTBL
		DC.L	SIXTEENColor-EXTBL
		DC.L	THRTWOColor-EXTBL
		DC.L	BWtoD15Alpha-EXTBL		;56		<42>
		DC.L	BWtoD24Alpha-EXTBL		;60		<42>
;		DC.L	BWtoD15-EXTBL
;		DC.L	BWtoD24-EXTBL


	ALIGN 	4

;-----------------------------------------------
;
;  TABLE OF POINTERS TO THE STRETCH ROUTINES
;  USED BY PATEXPAND
;
PATEXTBL
		DC.L	ONE1-PATEXTBL
		DC.L	DOUBLE1-PATEXTBL
		DC.L	QUAD1-PATEXTBL
		DC.L	EIGHT1-PATEXTBL
		DC.L	SXTN1-PATEXTBL
		DC.L	THRTWO1-PATEXTBL


	ALIGN 	Alignment

;-----------------------------------------------
;
;  NUMERATOR = DENOMINATOR, JUST COPY LONGS
;
ONE 	SUB.L	A1,A2						;Get byte count
		MOVE.L	A2,D0						;
		LSR.L	#2,D0						;Get count of longs
		SUBQ	#1,D0						;less one for the dbra
@1		MOVE.L	(A0)+,(A1)+ 				;COPY ONE LONG
		DBRA	D0,@1						;IS DSTPTR >= DSTLIMIT ?
		RTS 								;ALL DONE

	ALIGN 	Alignment

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

OneColor
		move.l	fcolor(a6),d3
		move.l	bcolor(a6),d4

		MOVE.L	A2,D1						; D3->last address we write to
		SUB.L	A1,D1						; D3 = number of bytes to write
		LSR		#2,D1						; divided in 4 to write longs
		SUBQ	#1,D1						; less one for DBRA
@a		MOVE.l	(A0)+,D2					; fetch long
;
;colorize
;
		MOVE.L	D2,D5						;copy of source
		NOT.L	D2							;turn on background bits
		AND.L	D3,D5						;color same as background color
		AND.L	D4,D2						;color foreground bits same as foreground color
		OR.L	D5,D2						;combine colored foreground and background bits
		move.l	d2,(A1)+					; send its double out
		DBRA	D1,@a
		RTS

	ALIGN 	Alignment

; EXPAND AN 8*8 PATTERN (ONE BIT DEEP)

ONE1	CLR.W	(A1)+						;CLEAR PATROW
		CLR.L	(A1)+						;CLEAR PATHMASK, PATVMASK
		MOVE.L	(A1),A1						;GET EXPAT POINTER
		MOVE.B	(A0)+,D0					;GET FIRST BYTE OF PATTERN
		bra.s	@first

@0		MOVE.B	(A0)+,D0					;GET A BYTE OF PATTERN
		cmp.b	D5,D0						;Same as last time?
		beq.s	@again
@first	move.b	D0,D5						;cache for later

		EOR.B	D7,D0						;INVERT IT IF MODE BIT 2
		ROL.B	D2,D0						;ALIGN TO LOCAL COORDS

		MOVE.B	D0,D1						;JUST REPLICATE
		LSL.L	#8,D1
		MOVE.B	D0,D1						;TWICE IN LOW WORD
		MOVE	D1,D0
		SWAP	D1
		MOVE	D0,D1						;PUT IN HIGH WORD TOO

		MOVE.L	D1,D0						;COPY PATTERN BYTE
		AND.L	D3,D0						;GET LONG OF FG DATA
		NOT.L	D1							;GET NOTMASK
		AND.L	D4,D1						;GET LONG OF BK DATA
		OR.L	D0,D1						;COMBINE THEM
@again	MOVE.L	D1,(A1)+					;PUT A LONG
		MOVE.L	D1,32-4(A1)					;PUT ANOTHER LONG

		DBRA	D6,@0						;REPEAT FOR ALL BYTES
		RTS

	ALIGN 	Alignment

;---------------------------------------------------
;
;  SHRINK TO THREE QUARTERS.
;
THREE4	MOVEQ	#3,D3						;MASK FOR HI 2 BITS
		ROR.L	#2,D3						;IE. $C0000000
THREE4A MOVE.L	(A0)+,D0					;GET A LONG OF SRC
		MOVEQ	#7,D2						;INIT COUNT OF 24 DST BITS
THREE4B ADD.L	D0,D0						;GET 1 BIT OF SRC
		ADDX.L	D1,D1						;PUT 1 BIT TO DST
		ADD.L	D3,D0						;PUT HI 2 BITS INTO CARRY
		ADDX.L	D1,D1						;SHIFT INTO DST
		LSL.L	#3,D0						;SHIFT LEFT 3 BITS
		ADDX.L	D1,D1						;PUT CARRY BIT INTO DST
		DBRA	D2,THREE4B					;LOOP 8 TIMES

		BFINS	D1,(A1){0:24}
		ADDQ	#3,A1
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO 	THREE4A 					;NO, CONTINUE
		RTS 								;AND QUIT


	ALIGN 	Alignment

;---------------------------------------------------
;
;  SHRINK TO ONE HALF.
;

Half	MOVE.L	A2,D3
		SUB.L	A1,D3
		LSR		#2,D3				; We'll be doing longwords
		SUBQ	#1,D3				; less one for dbra
		MOVE.L	#$55555555,D2		; alternate bits
		MOVE.L	#$00FF00FF,D5			; mask for byte index

@a		MOVE.L	(A0)+,D0			; fetch a source word
		MOVE.L	D0,D1				; copy it
		LSR.L	#1,D1				; shift copy right
		OR.L	D0,D1				; or original with shift
		AND.L	D2,D1				; Do some masking. bits: F.E.D.C.B.A.9.8.7.6.5.4.3.2.1.0
		MOVE.L	D1,D0				; copy masked ored word
		LSR.L	#7,D0				; downshift: D0 = ........F.E.D.C.B.A.9.8.7.6.5.4.
		OR.L	D1,D0				; or the low bits: D0 = ........FBEAD9C8xxxxxxxx73625140
		AND.L	D5,D0				; Mask it to two byte indices
		SWAP	D0
		MOVE.B	TableHalf(D0),D4	; unscramble the bits
		LSL		#8,D4
		SWAP	D0
		MOVE.B	TableHalf(D0),D4
		SWAP	D4					; D4 has 1st two words to send out

		MOVE.L	(A0)+,D0			; fetch another source word
		MOVE.L	D0,D1				; copy it
		LSR.L	#1,D1				; shift copy right
		OR.L	D0,D1				; or original with shift
		AND.L	D2,D1				; Do some masking. bits: F.E.D.C.B.A.9.8.7.6.5.4.3.2.1.0
		MOVE.L	D1,D0				; copy masked ored word
		LSR.L	#7,D0				; downshift: D0 = ........F.E.D.C.B.A.9.8.7.6.5.4.
		OR.L	D1,D0				; or the low bits: D0 = ........FBEAD9C8xxxxxxxx73625140
		AND.L	D5,D0				; Mask it to two byte indices
		SWAP	D0
		MOVE.B	TableHalf(D0),D4	; unscramble the bits
		LSL		#8,D4
		SWAP	D0
		MOVE.B	TableHalf(D0),D4
		MOVE.L	D4,(A1)+				; put out four bytes (from eight)
		DBRA	D3,@a
		RTS

TableHalf
	DC.B	$00,$01,$10,$11,$02,$03,$12,$13,$20,$21,$30,$31,$22,$23,$32,$33
	DC.B	$04,$05,$14,$15,$06,$07,$16,$17,$24,$25,$34,$35,$26,$27,$36,$37
	DC.B	$40,$41,$50,$51,$42,$43,$52,$53,$60,$61,$70,$71,$62,$63,$72,$73
	DC.B	$44,$45,$54,$55,$46,$47,$56,$57,$64,$65,$74,$75,$66,$67,$76,$77
	DC.B	$08,$09,$18,$19,$0a,$0b,$1a,$1b,$28,$29,$38,$39,$2a,$2b,$3a,$3b
	DC.B	$0c,$0d,$1c,$1d,$0e,$0f,$1e,$1f,$2c,$2d,$3c,$3d,$2e,$2f,$3e,$3f
	DC.B	$48,$49,$58,$59,$4a,$4b,$5a,$5b,$68,$69,$78,$79,$6a,$6b,$7a,$7b
	DC.B	$4c,$4d,$5c,$5d,$4e,$4f,$5e,$5f,$6c,$6d,$7c,$7d,$6e,$6f,$7e,$7f
	DC.B	$80,$81,$90,$91,$82,$83,$92,$93,$a0,$a1,$b0,$b1,$a2,$a3,$b2,$b3
	DC.B	$84,$85,$94,$95,$86,$87,$96,$97,$a4,$a5,$b4,$b5,$a6,$a7,$b6,$b7
	DC.B	$c0,$c1,$d0,$d1,$c2,$c3,$d2,$d3,$e0,$e1,$f0,$f1,$e2,$e3,$f2,$f3
	DC.B	$c4,$c5,$d4,$d5,$c6,$c7,$d6,$d7,$e4,$e5,$f4,$f5,$e6,$e7,$f6,$f7
	DC.B	$88,$89,$98,$99,$8a,$8b,$9a,$9b,$a8,$a9,$b8,$b9,$aa,$ab,$ba,$bb
	DC.B	$8c,$8d,$9c,$9d,$8e,$8f,$9e,$9f,$ac,$ad,$bc,$bd,$ae,$af,$be,$bf
	DC.B	$c8,$c9,$d8,$d9,$ca,$cb,$da,$db,$e8,$e9,$f8,$f9,$ea,$eb,$fa,$fb
	DC.B	$cc,$cd,$dc,$dd,$ce,$cf,$de,$df,$ec,$ed,$fc,$fd,$ee,$ef,$fe,$ff


	ALIGN 	Alignment

;---------------------------------------------------
;
;  SHRINK TO ONE QUARTER.
;
QRTR	MOVE.L	#$F0000000,D3				;MASK FOR HI 4 BITS
QRTR1	MOVE.L	(A0)+,D0					;GET A LONG OF SRC
		MOVEQ	#7,D2						;INIT COUNT OF 8 DST BITS
QRTR2	ADD.L	D3,D0						;PUT OR OF HI BITS INTO CARRY
		ADDX.L	D1,D1						;SHIFT BIT INTO DST
		LSL.L	#4,D0						;SHIFT LEFT 4 BITS
		DBRA	D2,QRTR2					;LOOP 8 TIMES
		MOVE.B	D1,(A1)+					;THEN PUT A BYTE TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO 	QRTR1						;NO, CONTINUE
		RTS 								;YES, QUIT


	ALIGN 	Alignment

;---------------------------------------------------
;
;  SHRINK TO ONE EIGHTH.
;
EIGHTH	MOVE.L	#$FF000000,D3				;MASK FOR HI 8 BITS
EIGHTH1	MOVE.L	(A0)+,D0					;GET A LONG OF SRC
		MOVEQ	#3,D2						;INIT COUNT OF 4 DST BITS
EIGHTH2	ADD.L	D3,D0						;PUT OR OF HI BITS INTO CARRY
		ADDX.L	D1,D1						;SHIFT BIT INTO DST
		LSL.L	#8,D0						;SHIFT LEFT 8 BITS
		DBRA	D2,EIGHTH2					;LOOP 8 TIMES
		MOVE.L	(A0)+,D0					;GET A LONG OF SRC
		MOVEQ	#3,D2						;INIT COUNT OF 4 DST BITS
EIGHTH3	ADD.L	D3,D0						;PUT OR OF HI BITS INTO CARRY
		ADDX.L	D1,D1						;SHIFT BIT INTO DST
		LSL.L	#8,D0						;SHIFT LEFT 8 BITS
		DBRA	D2,EIGHTH3					;LOOP 8 TIMES
		MOVE.B	D1,(A1)+					;THEN PUT A BYTE TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO 	EIGHTH1						;NO, CONTINUE
		RTS 								;YES, QUIT


	ALIGN 	Alignment

;-----------------------------------------------
;
;  STRETCH TO 1.5 TIMES AS WIDE
;
ONE_5	MOVE.B	(A0)+,D0					;GET FIRST BYTE FROM SRC
		MOVE	D0,D1						;MAKE AN EXTRA COPY
		LSR.B	#4,D1						;GET HI NIBBLE
		MOVE.B	TABLE15(D1),D2				;EXPAND TO 6 BITS
		LSL.L	#6,D2						;SHIFT OVER 6
		AND 	#$F,D0						;GET LO NIBBLE
		MOVE.B	TABLE15(D0),D2				;EXPAND TO 6 BITS
		LSL.L	#6,D2						;SHIFT OVER 6
		MOVE.B	(A0)+,D0					;GET SECOND BYTE FROM SRC
		MOVE	D0,D1						;MAKE AN EXTRA COPY
		LSR.B	#4,D1						;GET HI NIBBLE
		MOVE.B	TABLE15(D1),D2				;EXPAND TO 6 BITS
		LSL.L	#6,D2						;SHIFT OVER 6
		AND 	#$F,D0						;GET LO NIBBLE
		MOVE.B	TABLE15(D0),D2				;EXPAND TO 6 BITS
		LSR.L	#2,D2						;RIGHT JUSTIFY
		SWAP	D2							;FLIP WORDS
		MOVE.B	D2,(A1)+					;PUT FIRST BYTE TO DST
		SWAP	D2							;FLIP BACK AGAIN
		MOVE	D2,D1
		ROR 	#8,D1
		MOVE.B	D1,(A1)+					;PUT SECOND BYTE TO DST
		MOVE.B	D2,(A1)+					;PUT THIRD BYTE TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO 	ONE_5						;NO, LOOP FOR MORE
		RTS 								;ALL DONE

TABLE15 DC.B	$00,$0C,$10,$1C 			;1.5 TIMES TABLE
		DC.B	$60,$6C,$70,$7C
		DC.B	$80,$8C,$90,$9C
		DC.B	$E0,$EC,$F0,$FC


	ALIGN 	Alignment

;-----------------------------------------------
;
;  DOUBLE USING TABLE LOOKUP
;

Double1 CLR.W	(A1)+					;CLEAR PATROW
		CLR.L	(A1)+					;CLEAR PATHMASK, PATVMASK
		MOVE.L	(A1),A1					;GET EXPAT POINTER
		moveq	#0,d0
		MOVE.B	(A0)+,D0				;GET First BYTE OF PATTERN
		bra.s	@first

@0		MOVEQ	#0,D0					;CLEAR OUT HIGH PART
		MOVE.B	(A0)+,D0				;GET A BYTE OF PATTERN
		cmp.b	D5,D0						;Same as last time?
		beq.s	@again
@first	move.b	D0,D5						;cache for later

		EOR.B	D7,D0					;INVERT IT IF MODE BIT 2
		ROL.B	D2,D0					;ALIGN TO LOCAL COORDS

		MOVE.W	D0,D1					;MAKE AN EXTRA COPY
		MOVE	Table2(D1*2),D1			;DOUBLE Byte to Word
		MOVE	D1,D0					;COPY
		SWAP 	D1						;SWAP
		MOVE	D0,D1					;RETURN ENTIRE LONG

		MOVE.L	D1,D0					;COPY FOR NOTMASK
		AND.L	D3,D0					;GET LONG OF FG DATA
		NOT.L	D1						;GET NOTMASK
		AND.L	D4,D1					;GET LONG OF BK DATA
		OR.L	D0,D1					;COMBINE THEM
@again	MOVE.L	D1,32(A1)				;PUT ANOTHER LONG
		MOVE.L	D1,(A1)+				;PUT A LONG

		DBRA	D6,@0					;REPEAT FOR EACH BYTE
		RTS 							;ALL DONE

	ALIGN 	Alignment

Double	CLR		D0						; incoming bytes'll go here
		MOVE.L	A2,D3					; D3->last address we write to
		SUB.L	A1,D3					; D3 = number of bytes to write
		LSR		#1,D3					; divided in half, because we write words
		SUBQ	#1,D3					; less one for DBRA
@a		MOVE.B	(A0)+,D0				; fetch a byte
		MOVE	Table2(D0*2),(A1)+		; send its double out
		DBRA	D3,@a
		RTS

	ALIGN 	Alignment

; from QDciPatchROM.a without trashing A3									<sm 6/9/92>stb

DoubleColor
		move.l	fcolor(a6),d3
		move.l	bcolor(a6),d4

		CLR		D0						; incoming bytes'll go here
		MOVE.L	A2,D1					; D3->last address we write to
		SUB.L	A1,D1					; D3 = number of bytes to write
		LSR		#1,D1					; divided in half, because we write words
		SUBQ	#1,D1					; less one for DBRA
@a		MOVE.B	(A0)+,D0				; fetch a byte
		MOVE	Table2(D0*2),d2
;
;colorize
;
		MOVE.L	D2,D5			;copy of source
		NOT.L	D2				;turn on background bits
		AND.L	D3,D5			;color same as background color
		AND.L	D4,D2			;color foreground bits same as foreground color
		OR.L	D5,D2			;combine colored foreground and background bits
		move.w	d2,(A1)+		; send its double out
		DBRA	D1,@a
		RTS

Table2
		DC		$0000,$0003,$000c,$000f,$0030,$0033,$003c,$003f
		DC		$00c0,$00c3,$00cc,$00cf,$00f0,$00f3,$00fc,$00ff
		DC		$0300,$0303,$030c,$030f,$0330,$0333,$033c,$033f
		DC		$03c0,$03c3,$03cc,$03cf,$03f0,$03f3,$03fc,$03ff
		DC		$0c00,$0c03,$0c0c,$0c0f,$0c30,$0c33,$0c3c,$0c3f
		DC		$0cc0,$0cc3,$0ccc,$0ccf,$0cf0,$0cf3,$0cfc,$0cff
		DC		$0f00,$0f03,$0f0c,$0f0f,$0f30,$0f33,$0f3c,$0f3f
		DC		$0fc0,$0fc3,$0fcc,$0fcf,$0ff0,$0ff3,$0ffc,$0fff
		DC		$3000,$3003,$300c,$300f,$3030,$3033,$303c,$303f
		DC		$30c0,$30c3,$30cc,$30cf,$30f0,$30f3,$30fc,$30ff
		DC		$3300,$3303,$330c,$330f,$3330,$3333,$333c,$333f
		DC		$33c0,$33c3,$33cc,$33cf,$33f0,$33f3,$33fc,$33ff
		DC		$3c00,$3c03,$3c0c,$3c0f,$3c30,$3c33,$3c3c,$3c3f
		DC		$3cc0,$3cc3,$3ccc,$3ccf,$3cf0,$3cf3,$3cfc,$3cff
		DC		$3f00,$3f03,$3f0c,$3f0f,$3f30,$3f33,$3f3c,$3f3f
		DC		$3fc0,$3fc3,$3fcc,$3fcf,$3ff0,$3ff3,$3ffc,$3fff
		DC		$c000,$c003,$c00c,$c00f,$c030,$c033,$c03c,$c03f
		DC		$c0c0,$c0c3,$c0cc,$c0cf,$c0f0,$c0f3,$c0fc,$c0ff
		DC		$c300,$c303,$c30c,$c30f,$c330,$c333,$c33c,$c33f
		DC		$c3c0,$c3c3,$c3cc,$c3cf,$c3f0,$c3f3,$c3fc,$c3ff
		DC		$cc00,$cc03,$cc0c,$cc0f,$cc30,$cc33,$cc3c,$cc3f
		DC		$ccc0,$ccc3,$cccc,$cccf,$ccf0,$ccf3,$ccfc,$ccff
		DC		$cf00,$cf03,$cf0c,$cf0f,$cf30,$cf33,$cf3c,$cf3f
		DC		$cfc0,$cfc3,$cfcc,$cfcf,$cff0,$cff3,$cffc,$cfff
		DC		$f000,$f003,$f00c,$f00f,$f030,$f033,$f03c,$f03f
		DC		$f0c0,$f0c3,$f0cc,$f0cf,$f0f0,$f0f3,$f0fc,$f0ff
		DC		$f300,$f303,$f30c,$f30f,$f330,$f333,$f33c,$f33f
		DC		$f3c0,$f3c3,$f3cc,$f3cf,$f3f0,$f3f3,$f3fc,$f3ff
		DC		$fc00,$fc03,$fc0c,$fc0f,$fc30,$fc33,$fc3c,$fc3f
		DC		$fcc0,$fcc3,$fccc,$fccf,$fcf0,$fcf3,$fcfc,$fcff
		DC		$ff00,$ff03,$ff0c,$ff0f,$ff30,$ff33,$ff3c,$ff3f
		DC		$ffc0,$ffc3,$ffcc,$ffcf,$fff0,$fff3,$fffc,$ffff



	ALIGN 	Alignment

;-----------------------------------------------
;
;  TRIPLE USING TABLE LOOKUP
;
TRIPLE	MOVE.B	(A0)+,D0					;GET A BYTE FROM SRC
		MOVE	D0,D1						;MAKE AN EXTRA COPY
		MOVE	D0,D2						;MAKE A THIRD COPY
		LSR.B	#5,D2						;GET 3 HI BITS
		MOVE.B	TABLE3A(D2),(A1)+			;PUT FIRST BYTE TO DST
		LSR.B	#2,D1
		AND 	#$F,D1						;GET MIDDLE 4 BITS
		MOVE.B	TABLE3B(D1),(A1)+			;PUT SECOND BYTE TO DST
		AND 	#$7,D0						;GET 3 LO BITS
		MOVE.B	TABLE3C(D0),(A1)+			;PUT THIRD BYTE TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO 	TRIPLE						;NO, LOOP FOR MORE
		RTS 								;ALL DONE

TABLE3A DC.B	$00,$03,$1C,$1F 			;TRIPLING TABLE
		DC.B	$E0,$E3,$FC,$FF
TABLE3B DC.B	$00,$01,$0E,$0F
		DC.B	$70,$71,$7E,$7F
		DC.B	$80,$81,$8E,$8F
		DC.B	$F0,$F1,$FE,$FF
TABLE3C DC.B	$00,$07,$38,$3F
		DC.B	$C0,$C7,$F8,$FF


	ALIGN 	Alignment

;-----------------------------------------------
;
;  QUADRUPLE USING TABLE LOOKUP
;

QUAD 	SUB.L	A1,A2						;Get byte count
		MOVE.L	A2,D1						;
		LSR.L	#2,D1						;Get count of longs
		SUBQ	#1,D1						;less one for the dbra
@4		MOVE.B	(A0)+,D0					;GET A BYTE FROM SRC
		MOVE.L	TABLE4(D0*4),(A1)+			;AND SPIT OUT A LONG
		DBRA	D1,@4						;IS DSTPTR >= DSTLIMIT ?
		RTS 								;ALL DONE

	ALIGN 	Alignment

; from QDciPatchROM.a without trashing A3									<sm 6/9/92>stb

QUADColor
		move.l	fcolor(a6),d3
		move.l	bcolor(a6),d4

		SUB.L	A1,A2						;Get byte count
		MOVE.L	A2,D1						;
		LSR.L	#2,D1						;Get count of longs
		SUBQ	#1,D1						;less one for the dbra
@4		MOVE.B	(A0)+,D0					;GET A BYTE FROM SRC
		MOVE.L	TABLE4(D0*4),D2				;convert to a 4 bit/pixel
;
;colorize
;
		MOVE.L	D2,D5			;copy of source
		NOT.L	D2				;turn on background bits
		AND.L	D3,D5			;color same as background color
		AND.L	D4,D2			;color foreground bits same as foreground color
		OR.L	D5,D2			;combine colored foreground and background bits
		move.l	d2,(A1)+		;AND SPIT OUT A LONG
		DBRA	D1,@4						;IS DSTPTR >= DSTLIMIT ?
		RTS 								;ALL DONE

; QUAD INTO A LONG FOR PATTERNS

QUAD1	CLR.W	(A1)+						;CLEAR PATROW
		CLR.L	(A1)+						;CLEAR PATHMASK, PATVMASK
		MOVE.L	(A1),A1						;GET EXPAT POINTER
		moveq	#0,d0
		MOVE.B	(A0)+,D0					;GET First BYTE OF PATTERN
		bra.s	@first

@0		MOVEQ	#0,D0						;CLEAR OUT HIGH PART
		MOVE.B	(A0)+,D0					;GET A BYTE OF PATTERN
		cmp.b	D5,D0						;Same as last time?
		beq.s	@again
@first	move.b	D0,D5						;cache for later

		EOR.B	D7,D0						;INVERT IT IF MODE BIT 2
		ROL.B	D2,D0						;ALIGN TO LOCAL COORDS

		MOVE.L	TABLE4(D0*4),D1				;PUT A LONG TO D1
		MOVE.L	D1,D0						;COPY FOR NOTMASK
		AND.L	D3,D0						;GET LONG OF FG DATA
		NOT.L	D1							;GET NOTMASK
		AND.L	D4,D1						;GET LONG OF BK DATA
		OR.L	D0,D1						;COMBINE THEM
@again	MOVE.L	D1,(A1)+					;PUT A LONG
		MOVE.L	D1,32-4(A1)					;PUT ANOTHER LONG

		DBRA	D6,@0						;REPEAT FOR EACH BYTE
		RTS 								;ALL DONE


		ALIGN	4

TABLE4	DC.L	$00000000,$0000000F,$000000F0,$000000FF 	;QUADRUPLING TABLE
		DC.L	$00000F00,$00000F0F,$00000FF0,$00000FFF
		DC.L	$0000F000,$0000F00F,$0000F0F0,$0000F0FF
		DC.L	$0000FF00,$0000FF0F,$0000FFF0,$0000FFFF

		DC.L	$000F0000,$000F000F,$000F00F0,$000F00FF 	;QUADRUPLING TABLE
		DC.L	$000F0F00,$000F0F0F,$000F0FF0,$000F0FFF
		DC.L	$000FF000,$000FF00F,$000FF0F0,$000FF0FF
		DC.L	$000FFF00,$000FFF0F,$000FFFF0,$000FFFFF

		DC.L	$00F00000,$00F0000F,$00F000F0,$00F000FF 	;QUADRUPLING TABLE
		DC.L	$00F00F00,$00F00F0F,$00F00FF0,$00F00FFF
		DC.L	$00F0F000,$00F0F00F,$00F0F0F0,$00F0F0FF
		DC.L	$00F0FF00,$00F0FF0F,$00F0FFF0,$00F0FFFF

		DC.L	$00FF0000,$00FF000F,$00FF00F0,$00FF00FF 	;QUADRUPLING TABLE
		DC.L	$00FF0F00,$00FF0F0F,$00FF0FF0,$00FF0FFF
		DC.L	$00FFF000,$00FFF00F,$00FFF0F0,$00FFF0FF
		DC.L	$00FFFF00,$00FFFF0F,$00FFFFF0,$00FFFFFF

		DC.L	$0F000000,$0F00000F,$0F0000F0,$0F0000FF 	;QUADRUPLING TABLE
		DC.L	$0F000F00,$0F000F0F,$0F000FF0,$0F000FFF
		DC.L	$0F00F000,$0F00F00F,$0F00F0F0,$0F00F0FF
		DC.L	$0F00FF00,$0F00FF0F,$0F00FFF0,$0F00FFFF

		DC.L	$0F0F0000,$0F0F000F,$0F0F00F0,$0F0F00FF 	;QUADRUPLING TABLE
		DC.L	$0F0F0F00,$0F0F0F0F,$0F0F0FF0,$0F0F0FFF
		DC.L	$0F0FF000,$0F0FF00F,$0F0FF0F0,$0F0FF0FF
		DC.L	$0F0FFF00,$0F0FFF0F,$0F0FFFF0,$0F0FFFFF

		DC.L	$0FF00000,$0FF0000F,$0FF000F0,$0FF000FF 	;QUADRUPLING TABLE
		DC.L	$0FF00F00,$0FF00F0F,$0FF00FF0,$0FF00FFF
		DC.L	$0FF0F000,$0FF0F00F,$0FF0F0F0,$0FF0F0FF
		DC.L	$0FF0FF00,$0FF0FF0F,$0FF0FFF0,$0FF0FFFF

		DC.L	$0FFF0000,$0FFF000F,$0FFF00F0,$0FFF00FF 	;QUADRUPLING TABLE
		DC.L	$0FFF0F00,$0FFF0F0F,$0FFF0FF0,$0FFF0FFF
		DC.L	$0FFFF000,$0FFFF00F,$0FFFF0F0,$0FFFF0FF
		DC.L	$0FFFFF00,$0FFFFF0F,$0FFFFFF0,$0FFFFFFF

		DC.L	$F0000000,$F000000F,$F00000F0,$F00000FF 	;QUADRUPLING TABLE
		DC.L	$F0000F00,$F0000F0F,$F0000FF0,$F0000FFF
		DC.L	$F000F000,$F000F00F,$F000F0F0,$F000F0FF
		DC.L	$F000FF00,$F000FF0F,$F000FFF0,$F000FFFF

		DC.L	$F00F0000,$F00F000F,$F00F00F0,$F00F00FF 	;QUADRUPLING TABLE
		DC.L	$F00F0F00,$F00F0F0F,$F00F0FF0,$F00F0FFF
		DC.L	$F00FF000,$F00FF00F,$F00FF0F0,$F00FF0FF
		DC.L	$F00FFF00,$F00FFF0F,$F00FFFF0,$F00FFFFF

		DC.L	$F0F00000,$F0F0000F,$F0F000F0,$F0F000FF 	;QUADRUPLING TABLE
		DC.L	$F0F00F00,$F0F00F0F,$F0F00FF0,$F0F00FFF
		DC.L	$F0F0F000,$F0F0F00F,$F0F0F0F0,$F0F0F0FF
		DC.L	$F0F0FF00,$F0F0FF0F,$F0F0FFF0,$F0F0FFFF

		DC.L	$F0FF0000,$F0FF000F,$F0FF00F0,$F0FF00FF 	;QUADRUPLING TABLE
		DC.L	$F0FF0F00,$F0FF0F0F,$F0FF0FF0,$F0FF0FFF
		DC.L	$F0FFF000,$F0FFF00F,$F0FFF0F0,$F0FFF0FF
		DC.L	$F0FFFF00,$F0FFFF0F,$F0FFFFF0,$F0FFFFFF

		DC.L	$FF000000,$FF00000F,$FF0000F0,$FF0000FF 	;QUADRUPLING TABLE
		DC.L	$FF000F00,$FF000F0F,$FF000FF0,$FF000FFF
		DC.L	$FF00F000,$FF00F00F,$FF00F0F0,$FF00F0FF
		DC.L	$FF00FF00,$FF00FF0F,$FF00FFF0,$FF00FFFF

		DC.L	$FF0F0000,$FF0F000F,$FF0F00F0,$FF0F00FF 	;QUADRUPLING TABLE
		DC.L	$FF0F0F00,$FF0F0F0F,$FF0F0FF0,$FF0F0FFF
		DC.L	$FF0FF000,$FF0FF00F,$FF0FF0F0,$FF0FF0FF
		DC.L	$FF0FFF00,$FF0FFF0F,$FF0FFFF0,$FF0FFFFF

		DC.L	$FFF00000,$FFF0000F,$FFF000F0,$FFF000FF 	;QUADRUPLING TABLE
		DC.L	$FFF00F00,$FFF00F0F,$FFF00FF0,$FFF00FFF
		DC.L	$FFF0F000,$FFF0F00F,$FFF0F0F0,$FFF0F0FF
		DC.L	$FFF0FF00,$FFF0FF0F,$FFF0FFF0,$FFF0FFFF

		DC.L	$FFFF0000,$FFFF000F,$FFFF00F0,$FFFF00FF 	;QUADRUPLING TABLE
		DC.L	$FFFF0F00,$FFFF0F0F,$FFFF0FF0,$FFFF0FFF
		DC.L	$FFFFF000,$FFFFF00F,$FFFFF0F0,$FFFFF0FF
		DC.L	$FFFFFF00,$FFFFFF0F,$FFFFFFF0,$FFFFFFFF



	ALIGN 	Alignment

;-----------------------------------------------
;
;  STRETCH BY SIX USING TABLE LOOKUP
;
SIX 	MOVE.B	(A0)+,D0					;GET A BYTE FROM SRC
		MOVE	D0,D1						;MAKE AN EXTRA COPY
		AND 	#$E0,D1 					;MASK FOR HI 3 BITS
		LSR.B	#4,D1						;SHIFT FOR TABLE INDEX
		MOVE.W	TABLE6A(D1),(A1)+			;PUT A WORD TO DST
		MOVE	D0,D1						;GET SRC BYTE AGAIN
		AND 	#$3C,D1 					;MASK FOR MIDDLE 4 BITS
		LSR.B	#1,D1						;SHIFT FOR TABLE INDEX
		MOVE.W	TABLE6B(D1),(A1)+			;PUT A WORD TO DST
		MOVE	D0,D1						;GET SRC BYTE AGAIN
		AND 	#7,D1						;MASK FOR LO 3 BITS
		ADD 	D1,D1						;DOUBLE FOR TABLE INDEX
		MOVE.W	TABLE6C(D1),(A1)+			;PUT A WORD TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO 	SIX 						;NO, LOOP FOR MORE
		RTS 								;ALL DONE

TABLE6A DC.W	$0000,$000F,$03F0,$03FF 	;SIX TIMES TABLE
		DC.W	$FC00,$FC0F,$FFF0,$FFFF
TABLE6B DC.W	$0000,$0003,$00FC,$00FF
		DC.W	$3F00,$3F03,$3FFC,$3FFF
		DC.W	$C000,$C003,$C0FC,$C0FF
		DC.W	$FF00,$FF03,$FFFC,$FFFF
TABLE6C DC.W	$0000,$003F,$0FC0,$0FFF
		DC.W	$F000,$F03F,$FFC0,$FFFF

	ALIGN 	Alignment

; EXPAND AN 8*8 PATTERN FOR EIGHT BITS PER PIXEL

EIGHT1	MOVE	#8,(A1)+					;PATROW = 8
		MOVE	#$0004,(A1)+				;PATHMASK = $0004
		MOVE	#$003F,(A1)+				;PATVMASK = $003F

; IF PATTERN REPEATS ITSELF, THEN DO OLD WAY FOR SPEED.

		MOVE.L	A0,A2						;COPY PATTERN POINTER
		MOVEQ	#7,D0						;DO EIGHT BYTES
@0		MOVE.B	(A2),D1						;GET A BYTE
		ROR.B	#4,D1						;SWAP NIBBLES
		CMP.B	(A2)+,D1					;ARE THEY THE SAME?
		DBNE	D0,@0						;REPEAT FOR 8 BYTES
		BNE.S	@1							;=>NO, DO NEW WAY

		CLR		-6(A1)						;AND SET PATROW = 0
		BRA.S	Small8						;Pattern is in 1 long wide

@1		MOVE.L	(A1),A1						;GET EXPAT POINTER

FULL8	MOVEQ	#0,D1						;MAKE SURE HIGH PART IS 0
		MOVE.B	(A0)+,D1					;GET A BYTE OF PATTERN
		EOR.B	D7,D1						;INVERT IT IF MODE BIT 2
		ROL.B	D2,D1						;ALIGN TO LOCAL COORDS
		MOVE	D1,D5						;SAVE IN D5

		AND 	#$F0,D1 					;MASK FOR HI NIBBLE
		LSR		#2,D1						;SHIFT FOR TABLE INDEX
		MOVE.L	TABLE8(D1),D1				;PUT FIRST LONG TO DST
		MOVE.L	D1,D0						;COPY FOR NOTMASK
		AND.L	D3,D0						;GET LONG OF FG DATA
		NOT.L	D1							;GET NOTMASK
		AND.L	D4,D1						;GET LONG OF BK DATA
		OR.L	D0,D1						;COMBINE THEM
		MOVE.L	D1,(A1)+					;PUT A LONG

		AND 	#$0F,D5 					;MASK FOR LO NIBBLE
		MOVE.L	TABLE8(D5*4),D1				;PUT SECOND LONG TO DST
		MOVE.L	D1,D0						;COPY FOR NOTMASK
		AND.L	D3,D0						;GET LONG OF FG DATA
		NOT.L	D1							;GET NOTMASK
		AND.L	D4,D1						;GET LONG OF BK DATA
		OR.L	D0,D1						;COMBINE THEM
		MOVE.L	D1,(A1)+					;PUT A LONG

		DBRA	D6,FULL8					;REPEAT FOR EACH LONG
		RTS 								;ALL DONE



Small8	MOVE.L	(A1),A1						;GET EXPAT POINTER
		moveq	#0,d0
		MOVE.B	(A0)+,D0					;GET First BYTE OF PATTERN
		bra.s	@first

@NXT8	MOVEQ	#0,D0						;MAKE SURE HIGH PART IS 0
		MOVE.B	(A0)+,D0					;GET A BYTE OF PATTERN
		cmp.b	D5,D0						;Same as last time?
		beq.s	@again
@first	move.b	D0,D5						;cache for later

		EOR.B	D7,D0						;INVERT IT IF MODE BIT 2
		ROL.B	D2,D0						;ALIGN TO LOCAL COORDS

		AND 	#$F0,D0 					;MASK FOR HI NIBBLE
		LSR		#2,D0						;SHIFT FOR TABLE INDEX
		MOVE.L	TABLE8(D0),D1				;PUT FIRST LONG TO DST
		MOVE.L	D1,D0						;COPY FOR NOTMASK
		AND.L	D3,D0						;GET LONG OF FG DATA
		NOT.L	D1							;GET NOTMASK
		AND.L	D4,D1						;GET LONG OF BK DATA
		OR.L	D0,D1						;COMBINE THEM
@again	MOVE.L	D1,(A1)+					;PUT A LONG
		MOVE.L	D1,32-4(A1)					;MAKE 2 COPIES
		DBRA	D6,@NXT8					;REPEAT FOR EACH LONG
		RTS 								;ALL DONE

		ALIGN	4							;MOVED TABLE TO KEEP TABLE IN RANGE <22>

TABLE8	DC.L	$00000000,$000000FF,$0000FF00,$0000FFFF
		DC.L	$00FF0000,$00FF00FF,$00FFFF00,$00FFFFFF
		DC.L	$FF000000,$FF0000FF,$FF00FF00,$FF00FFFF
		DC.L	$FFFF0000,$FFFF00FF,$FFFFFF00,$FFFFFFFF

	ALIGN 	Alignment

;-----------------------------------------------
;
;  SCALE UP BY EIGHT USING TABLE LOOKUP
;

Eight
		MOVE.B	(A0)+,D0					;GET A BYTE OF SRC
		MOVE	D0,D1						;MAKE AN EXTRA COPY
		AND  	#$F0,D1 					;MASK FOR HI NIBBLE
		LSR		#2,D1						;SHIFT FOR TABLE INDEX
		MOVE.L	TABLE8(D1),(A1)+			;PUT FIRST LONG TO DST
		AND 	#$0F,D0 					;MASK FOR LO NIBBLE
		MOVE.L	TABLE8(D0*4),(A1)+			;PUT second LONG TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO.s 	Eight						;NO, GO FOR MORE
		RTS 								;ALL DONE



	ALIGN 	Alignment

;-----------------------------------------------
;
;  SCALE UP BY EIGHT USING TABLE LOOKUP, then colorize
;

; from QDciPatchROM.a but doesnÕt use A3 here								<sm 6/9/92>stb

EightLoop
		MOVE.B	(A0)+,D0					;GET A BYTE OF SRC
		MOVE	D0,D1						;MAKE AN EXTRA COPY
		AND 	#$F0,D1 					;MASK FOR HI NIBBLE
		LSR		#2,D1						;SHIFT FOR TABLE INDEX
		MOVE.L	TABLE8(D1),d2				;get four pixels
		AND 	#$0F,D0 					;MASK FOR LO NIBBLE
		MOVE.L	TABLE8(D0*4),D0				;get second set of four pixels
;
;colorize
;
		MOVE.L	D2,D5						;copy of source
		NOT.L	D2							;turn on background bits
		AND.L	D3,D5						;color same as background color
		AND.L	D4,D2						;color foreground bits same as foreground color
		OR.L	D5,D2						;combine colored foreground and background bits
		move.l	d2,(A1)+					;PUT FIRST LONG TO DST
;
;colorize
;
		MOVE.L	D0,D5						;copy of source
		NOT.L	D0							;turn on background bits
		AND.L	D3,D5						;color same as background color
		AND.L	D4,D0						;color foreground bits same as foreground color
		OR.L	D5,D0						;combine colored foreground and background bits

		move.l	D0,(A1)+					;PUT SECOND LONG TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		BLO.s 	EightLoop					;NO, GO FOR MORE
		RTS 								;ALL DONE


EIGHTColor
		move.l	fcolor(a6),d3
		move.l	bcolor(a6),d4
		bra.s	EightLoop					; HACK!!! Needed to keep Table8 in 8 bit range...<22>


	ALIGN 	Alignment

;-------------------------------------------------
;
;  SCALE UP BY 16	(thanks to Gary Davidian)
;
SIXTEEN
		MOVEQ	#15,D2						;16 output longs
		MOVE.L	(A0)+,D0					;fetch a long of src
@NxtBit	ADD.L	D0,D0						;extend first bit into hi word
		SUBX.L	D1,D1
		ADD.L	D0,D0						;extend next bit into lo word
		SUBX.W	D1,D1
		MOVE.L	D1,(A1)+
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		DBHS	D2,@NxtBit					;process remaining bits
		BLO 	SIXTEEN 					;fetch next input long
		RTS 								;ALL DONE


	ALIGN 	Alignment

; EXPAND AN 8*8 PATTERN FOR 16 BITS PER PIXEL
; *** DOESN'T CHECK FOR POSSIBLE SHORTCUT

SXTN1	MOVE	#16,(A1)+					;PATROW = 16
		MOVE	#$000C,(A1)+				;PATHMASK = $000C
		MOVE	#$007F,(A1)+				;PATVMASK = $007F

; IF PATTERN REPEATS ITSELF, THEN DO OLD WAY FOR SPEED.			<BAL 26Jun88>

		MOVE.L	A0,A2						;COPY PATTERN POINTER
		MOVEQ	#7,D0						;DO EIGHT BYTES
@0		MOVE.B	(A2)+,D1						;GET A BYTE
		MOVE.B	D1,D5						;MAKE A COPY
		ROR.B	#1,D1						;REALIGN BITS
		EOR.B	D1,D5						;ARE THEY THE SAME?
		BNE.S	@1							;=>NO, DO NEW WAY
		DBRA	D0,@0						;REPEAT FOR 8 BYTES

		BSET	#31,D6						;ELSE FLAG OLD WAY
		CLR		-6(A1)						;AND SET PATROW = 0

@1		MOVE.L	(A1),A1						;GET EXPAT POINTER

SXTN2	MOVE.B	(A0)+,D0					;GET A BYTE OF PATTERN
		EOR.B	D7,D0						;INVERT IT IF MODE BIT 2
		ROL.B	D2,D0						;ALIGN TO LOCAL COORDS

		MOVEQ	#7,D1						;ELSE 8 BITS PER BYTE
SXTN3 	ADD.B	D0,D0						;GET ONE BIT OF SRC
		BCS.S	FORE16	 					;BR IF FOREGROUND

BACK16	MOVE	D4,(A1)+					;PUT A WORD OF BACKGROUND TO DST
		TST.L	D6							;DO OLD WAY?
		BPL.S	@1							;NO, SKIP
		MOVE	D4,32-2(A1)					;YES, MAKE 2 COPIES
		SUBQ	#3,D1						;SHORT CIRCUIT INNER LOOP
@1		DBRA	D1,SXTN3					;LOOP UNTIL DONE
NXTBYT	DBRA	D6,SXTN2					;REPEAT FOR EACH BYTE
		RTS									;AND RETURN

FORE16	MOVE	D3,(A1)+					;PUT A WORD OF FOREGROUND TO DST
		TST.L	D6							;DO OLD WAY?
		BPL.S	@1							;NO, SKIP
		MOVE	D3,32-2(A1)					;YES, MAKE 2 COPIES
		SUBQ	#3,D1						;SHORT CIRCUIT INNER LOOP
@1		DBRA	D1,SXTN3					;LOOP UNTIL DONE
		DBRA	D6,SXTN2					;REPEAT FOR EACH BYTE
		RTS									;AND RETURN


	ALIGN 	Alignment

; EXPAND AN 8*8 PATTERN FOR 32 BITS PER PIXEL

THRTWO1 MOVE	#$20,(A1)+					;PATROW = 32
		MOVE	#$001C,(A1)+				;PATHMASK = $001C
		MOVE	#$00FF,(A1)+				;PATVMASK = $00FF

; IF SOLID PATTERN, THEN DO OLD WAY FOR SPEED.					<BAL 27Jun88>

		MOVE.L	A1,D5						;SAVE A COPY IN D5
		MOVE.L	(A1),A1						;GET EXPAT POINTER
		MOVE.L	A0,A2						;COPY PATTERN POINTER
		MOVEQ	#7,D0						;DO EIGHT BYTES

@NXTBYT	MOVE.B	(A2)+,D1					;GET A BYTE
		EOR.B	D7,D1						;INVERT IT IF MODE BIT 2
		BNE.S	@TRYFG						;SOLID 0's ?
		MOVE.L	D4,(A1)+					;YES, PUT A LONG OF BACKGROUND TO DST
		MOVE.L	D4,32-4(A1)					;YES, PUT A LONG OF BACKGROUND TO DST
		BRA.S	@LOOP

@TRYFG	ADDQ.B	#1,D1						;SOLID 1's ?
		BNE.S	@DONEW						;=>NO, DO NEW WAY
		MOVE.L	D3,(A1)+					;YES, PUT A LONG OF FOREGROUND TO DST
		MOVE.L	D3,32-4(A1)					;YES, PUT A LONG OF FOREGROUND TO DST
@LOOP	DBRA	D0,@NXTBYT					;REPEAT FOR 8 BYTES

		MOVE.L	D5,A1						;RESTORE A1
		CLR		-6(A1)						;FLAG OLD WAY: SET PATROW = 0
		RTS

; PATTERN DOESN'T FIT IN A LONG SO DO NEW WAY

@DONEW	MOVE.L	D5,A1						;RESTORE A1
		MOVE.L	(A1),A1						;GET EXPAT POINTER

THRTWO2	MOVE.B	(A0)+,D0					;GET A BYTE OF PATTERN
		EOR.B	D7,D0						;INVERT IT IF MODE BIT 2
		ROL.B	D2,D0						;ALIGN TO LOCAL COORDS

		MOVEQ	#7,D1						;8 BITS PER BYTE
THRTWO3 ADD.B	D0,D0						;GET ONE BIT OF SRC
		BCS.S	FORE32	 					;BR IF FOREGROUND

BACK32	MOVE.L	D4,(A1)+					;PUT A LONG OF BACKGROUND TO DST
		DBRA	D1,THRTWO3					;LOOP UNTIL DONE
		DBRA	D6,THRTWO2					;REPEAT FOR EACH BYTE
		RTS									;AND RETURN

FORE32 MOVE.L	D3,(A1)+					;PUT A LONG OF FOREGROUND TO DST
		DBRA	D1,THRTWO3					;LOOP UNTIL DONE
		DBRA	D6,THRTWO2					;REPEAT FOR EACH BYTE
		RTS									;AND RETURN


	ALIGN 	Alignment

;-----------------------------------------------
;
;  SCALE UP BY 32  (thanks to gary)
;
THRTWO
		MOVEQ	#31,D2						;32 output longs
		MOVE.L	(A0)+,D0					;fetch a long of src
@NxtBit	ADD.L	D0,D0						;extend high bit into long
		SUBX.L	D1,D1
		MOVE.L	D1,(A1)+
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		DBHS	D2,@NxtBit					;process remaining bits
		BLO 	THRTWO	 					;fetch next input long
		RTS 								;ALL DONE


	ALIGN 	Alignment

;-----------------------------------------------
;
;  SCALE UP FROM B/W 1-bit to 15 bit direct device (16 bits/pixel)		<BAL 06Dec88>
;
BWtoD15	MOVE.W	#$7fff,D2					;get high bit mask
		MOVE.L	A2,D3						;get limit ptr
		SUB.L	A1,D3						;get byte count in D3
		ROR.L	#6,D3						;D3.w = # of 32 words to build
		BRA.S	@Do32

@NxtLng	MOVEQ	#31,D4						;init bits per long counter
		MOVE.L	(A0)+,D0					;get next src long
		NOT.L	D0							;make 1's go to 1's
@NxtBit ADD.L	D0,D0						;get one bit of src into X bit
		SUBX.W	D1,D1						;get a word of X bits
		AND.W	D2,D1						;clear out high bit of pixel
		MOVE.W	D1,(A1)+ 					;dump out result
		DBRA	D4,@NxtBit					;continue for all bits in long
@Do32	DBRA	D3,@NxtLng					;go reload the source long

		CLR.W	D3							;clr out low word
		ROL.L	#5,D3						;get word cnt mod 32
		MOVE.L	(A0)+,D0					;get last src long
		NOT.L	D0
		BRA.S	@DoRest

@NxtOne ADD.L	D0,D0						;get one bit of src into X bit
		SUBX.W	D1,D1						;get a word of X bits
		AND.W	D2,D1						;clear out high bit of pixel
		MOVE.W	D1,(A1)+ 					;dump out result
@DoRest	DBRA	D3,@NxtOne					;go process another bit
		RTS

	ALIGN 	Alignment

;-------------------------------------------------
;
;  SCALE UP BY 16	(thanks to Gary Davidian)
;		with colorizing
;
; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

BWtoD15Alpha
		MOVE.L	alphaFore(A6),D3			;get alpha fg expansion mask	<42>
		MOVE.L	alphaBack(A6),D4			;get alpha bk expansion mask	<42>
		BRA.S	XXSIXTEEN					;fall into expansion code		<42>
SIXTEENColor
		move.l	fcolor(a6),d3
		move.l	bcolor(a6),d4
XXSIXTEEN
@SIXTEEN
		MOVEQ	#15,D2						;16 output longs
		MOVE.L	(A0)+,D0					;fetch a long of src
@NxtBit	ADD.L	D0,D0						;extend first bit into hi word
		SUBX.L	D1,D1
		ADD.L	D0,D0						;extend next bit into lo word
		SUBX.W	D1,D1
;
;colorize
;
		MOVE.L	D1,D5			;copy of source
		NOT.L	D1				;turn on background bits
		AND.L	D3,D5			;color same as background color
		AND.L	D4,D1			;color foreground bits same as foreground color
		OR.L	D5,D1			;combine colored foreground and background bits

		MOVE.L	D1,(A1)+
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		DBHS	D2,@NxtBit					;process remaining bits
		BLO 	@SIXTEEN 					;fetch next input long
		RTS 								;ALL DONE

	ALIGN 	Alignment

;-----------------------------------------------
;
;  SCALE UP BY 32  (thanks to gary)
;
; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

BWtoD24Alpha
		MOVE.L	alphaFore(A6),D3			;get alpha fg expansion mask	<42>
		MOVE.L	alphaBack(A6),D4			;get alpha bk expansion mask	<42>
		BRA.S	XXTHRTWO					;fall into expansion code		<42>
THRTWOColor
		move.l	fcolor(a6),d3
		move.l	bcolor(a6),d4
XXTHRTWO
@THRTWO
		MOVEQ	#31,D2						;32 output longs
		MOVE.L	(A0)+,D0					;fetch a long of src
@NxtBit	ADD.L	D0,D0						;extend high bit into long
		SUBX.L	D1,D1
;
;colorize
;
		MOVE.L	D1,D5			;copy of source
		NOT.L	D1				;turn on background bits
		AND.L	D3,D5			;color same as background color
		AND.L	D4,D1			;color foreground bits same as foreground color
		OR.L	D5,D1			;combine colored foreground and background bits

		MOVE.L	D1,(A1)+
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		DBHS	D2,@NxtBit					;process remaining bits
		BLO 	@THRTWO	 					;fetch next input long
		RTS 								;ALL DONE

	ALIGN 	Alignment

;-----------------------------------------------
;
;  SCALE UP FROM B/W 1-bit to 24 bit direct device (32 bits/pixel)		<BAL 28Jun 88>
;
BWtoD24 MOVE.L	maskBC,D2					;high byte clearing mask
		MOVE.L	A2,D3						;get limit ptr
		SUB.L	A1,D3						;get byte count in D3
		ROR.L	#7,D3						;D3.w = # of 32 longs to build
		BRA.S	@Do32

@NxtLng	MOVEQ	#31,D4						;init bits per long counter
		MOVE.L	(A0)+,D0					;get next src long
		NOT.L	D0
@NxtBit ADD.L	D0,D0						;get one bit of src into X bit
		SUBX.L	D1,D1						;get a word of X bits
		AND.L	D2,D1						;clear out high bit of pixel
		MOVE.L	D1,(A1)+ 					;dump out result
		DBRA	D4,@NxtBit					;continue for all bits in long
@Do32	DBRA	D3,@NxtLng					;go reload the source long

		CLR.W	D3							;clr out low word
		ROL.L	#5,D3						;get long cnt mod 32
		MOVE.L	(A0)+,D0					;get last src long
		NOT.L	D0
		BRA.S	@DoRest

@NxtOne ADD.L	D0,D0						;get one bit of src into X bit
		SUBX.L	D1,D1						;get a word of X bits
		AND.L	D2,D1						;clear out high bit of pixel
		MOVE.L	D1,(A1)+ 					;dump out result
@DoRest	DBRA	D3,@NxtOne					;go process another bit
		RTS


	ALIGN 	Alignment


;-----------------------------------------------
;
;  SCALE UP BY ANY MULTIPLE OF 8 GREATER THAN 2
;
EIGHTS	LSR 	#3,D4						;DIVIDE SCALE FACTOR BY 8
		SUB 	#1,D4						;SUB 1 FOR LOOP COUNT
		MOVE	#$8000,D0					;INIT SRC DATA
EIGHTS1 ADD 	D0,D0						;GET ONE SRC BIT IN CARRY
		BNE.S	EIGHTS2 					;TIME FOR NEW SRC ?
		MOVE	(A0)+,D0					;YES, GET NEXT SRC LONG
		ADDX	D0,D0						;SHIFT SRC BIT OUT, 1 BIT IN
EIGHTS2 SCS 	D1							;SET OR CLR A BYTE
		MOVE	D4,D2						;INIT LOOP COUNT
EIGHTS3 MOVE.B	D1,(A1)+					;PUT ONE BYTE TO DST
		CMP.L	A2,A1						;IS DSTPTR >= DSTLIMIT ?
		DBHI	D2,EIGHTS3					;LOOP TILL SCALE OR DST FULL
		BLS 	EIGHTS1 					;MORE SRC IF DST NOT FULL
		rts									;THEN QUIT					@@@@ 04May88 BAL used to be BRA DONE


	IF 0 THEN
;------------------------------------------------------------------
;
;  DO FULL RATIO SCALING, SHRINKING ONE BIT AT A TIME
;
SHRINK	MOVEM.L	D7/D6,-(SP)					;save d7

		MOVEQ 	#0,D1						;INIT DST WORD
		MOVE	#$1F,D2						;init bit counter
		MOVEQ	#1,D0						;GET 1 INTO HIGH BIT
		ROR.L	#1,D0						;TO INIT DATA STREAM
		MOVE.L	D4,D3						;COPY RATIO
		LSR.L	#1,D3						;INIT ERR TO RATIO/2
		MOVE.L	D3,D7						;init bit accum to ratio/2
		MOVEQ	#1,D6						;use D6 to test for overflow
		SWAP	D6							;into high word 

NXTSRC1 ADD.L	D0,D0						;GET SRC BIT
		BCC.S	WHITE1						;BRANCH IF WHITE
		BNE.S	BLACK1						;BRANCH IF BLACK
		MOVE.L	(A0)+,D0					;ELSE GET NEW SRC WORD
		ADDX.L	D0,D0						;GET SRC BIT
		BCC.S	WHITE1						;AND CONTINUE

BLACK1	ADD.L	D4,D7						;add weight of a set bit
WHITE1	CMP.L	D6,D7						;overflow into high word yet?
		BLE.S	FSCAN						;=>no, continue scanning
		BSET	D2,D1						;else set the bit
		BNE.S	FSCAN						;=>if already set, save for next time
		SUB.L	D6,D7						;subtract one for bit we set
FSCAN	ADD 	D4,D3						;TIME FOR NEXT DSTBIT ?
		BCC 	NXTSRC1 					;NO, LOOP MORE SRC
		SUBQ 	#1,D2						;yes, do next bit
		BPL.S 	NXTSRC1 					;loop if dst word ok
		MOVE.L	D1,(A1)+					;ELSE WRITE WORD TO DST
		MOVEQ 	#0,D1						;INIT DST WORD
		MOVE	#$1F,D2						;and reset bit counter
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT ?
		BLO.S	NXTSRC1 					;NO, LOOP

		MOVEM.L	(SP)+,D7/D6					;restore d7
		RTS 								;YES, QUIT

	ELSE

	ALIGN 	Alignment

;------------------------------------------------------------------
;
;  DO FULL RATIO SCALING, SHRINKING ONE BIT AT A TIME
;
SHRINK	CLR 	D1							;INIT DST WORD
		MOVE	#$8000,D0					;INIT SRC WORD
		MOVE	D0,D2						;INIT MASK
		MOVE	D4,D3						;COPY RATIO
		LSR 	#1,D3						;INIT ERR TO RATIO/2

NXTSRC1 ADD 	D0,D0						;GET SRC BIT
		BCC.S	WHITE1						;BRANCH IF WHITE
		BNE.S	BLACK1						;BRANCH IF BLACK
		MOVE	(A0)+,D0					;ELSE GET NEW SRC WORD
		ADDX	D0,D0						;GET SRC BIT
		BCC.S	WHITE1						;AND CONTINUE

BLACK1	OR		D2,D1						;SET A BIT IN DST
WHITE1	ADD 	D4,D3						;TIME FOR NEXT DSTBIT ?
		BCC 	NXTSRC1 					;NO, LOOP MORE SRC
		ROR 	#1,D2						;YES, ROTATE MASK
		BCC 	NXTSRC1 					;LOOP IF DST WORD OK
		MOVE	D1,(A1)+					;ELSE WRITE WORD TO DST
		CLR 	D1							;RESET DST WORD
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT ?
		BLO 	NXTSRC1 					;NO, LOOP
		RTS 								;YES, QUIT

	ENDIF


	ALIGN 	Alignment

;------------------------------------------------------------------
;
;  DO FULL RATIO SCALING, STRETCHING ONE BIT AT A TIME
;
STRCH 	CLR 	D1							;INIT DST WORD
		MOVE	#$8000,D0					;INIT SRC WORD
		MOVE	D0,D2						;INIT MASK
		MOVE	D4,D3						;COPY RATIO
		LSR 	#1,D3						;INIT ERR TO RATIO/2

@NXTSRC	ADD 	D0,D0						;GET SRC BIT
		BCC.S	@WHITE						;BRANCH IF WHITE
		BNE.S	@BLACK						;BRANCH IF BLACK
		MOVE	(A0)+,D0					;ELSE GET NEW SRC WORD
		ADDX	D0,D0						;GET SRC BIT
		BCC.S	@WHITE						;CONTINUE WITH WHITE
		BRA.S	@BLACK						;CONTINUE WITH BLACK

@BLKOK	ADD 	D4,D3						;TIME FOR NEXT SRC BIT ?
		BCS 	@NXTSRC 					;YES, LOOP FOR SRC
@BLACK	OR		D2,D1						;SET A BIT OF DST
		ROR 	#1,D2						;ROTATE MASK
		BCC 	@BLKOK 						;LOOP IF DST WORD OK
		MOVE	D1,(A1)+					;ELSE WRITE WORD TO DST
		CLR 	D1							;RESET DST WORD
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT ?
		BLO 	@BLKOK 						;NO, LOOP
		RTS 								;YES, QUIT

@WHTOK	ADD 	D4,D3							;TIME FOR NEXT SRC BIT ?
		BCS 	@NXTSRC 					;YES, LOOP FOR SRC
@WHITE	ROR 	#1,D2						;ROTATE MASK
		BCC 	@WHTOK 						;LOOP IF DST WORD OK
		MOVE	D1,(A1)+					;ELSE WRITE WORD TO DST
		CLR 	D1							;RESET DST WORD
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT ?
		BLO 	@WHTOK 						;NO, LOOP

@DONE	RTS

	IF 0 THEN

;------------------------------------------------------------------
;
;  DO FULL-RATIO COLOR SCALING, SHRINKING ONE PIXEL AT A TIME
;	altered to use area averaging 9/3/88 BAL
;

;			D0.L = src data			A0.L = ptr to src scan
;			D1.L = dst data			A1.L = ptr to dst scan
;			D2.L = src offset		A2.L = limit ptr
;			D3.W = error term		A3.W = ratio < 1.0
;			D4.L = scratch			A4 = scratch
;			D5.W = bits/pixel		A5 = scratch
;			D6.L = dst offset		A6 = locals
;			D7.W = long mask		A7 = stack

;ciPIXSHRNK
PIXSHRNK
		tst.b	useAverage(a6)				;use area averaging?
		bne.s	averageH					;yes, average pixels

	;Not 32 bit deep so point sample for now:

		MOVEM.L	D6/D7,-(SP)					;SAVE WORK REGISTERS
		MOVE	D4,A3						;GET RATIO IN A3
		MOVE	D4,D3						;COPY RATIO
		LSR 	#1,D3						;INIT ERR TO RATIO/2
		MOVEQ	#0,D2						;INIT OFFSET INTO SRC
		MOVEQ	#0,D6						;INIT OFFSET INTO DST
		MOVEQ	#$1F,D7						;GET MASK FOR LONGS
		;EXT.L	D5							;MAKE SURE D5 IS LONG
		MOVE.L	(A0)+,D0					;GET FIRST SRC LONG
		MOVEQ	#0,D1						;INIT FIRST DST LONG TO 0
@NXTDST	;SUB.L	A4,A4						;INIT DST PIXEL VALUE TO 0
@NXTSRC	;BFEXTU	D0{D2:D5},D4				;GET A PIXEL OF SRC
		;CMP.L	A4,D4						;COMPARE AGAINST DST
		;BLS.S	@ADVSRC						;IF SRC < DST, DON'T REPLACE
		;BFINS	D4,D1{D6:D5}				;ELSE REPLACE PIXEL
		;MOVE.L	D4,A4						;AND SAVE AS DST CONTENTS
@ADVSRC	ADD.L	D5,D2						;BUMP TO NEXT SRC PIXEL
		AND		D7,D2						;TIME FOR NEXT SRC LONG?
		BNE.S	@0							;=>NO
		MOVE.L	(A0)+,D0					;ELSE GET NEXT SRC LONG
@0		ADD		A3,D3						;TIME FOR NEXT DST PIXEL?
		BCC.S	@NXTSRC	 					;NO, GET NEXT SRC PIXEL

		BFEXTU	D0{D2:D5},D4				;GET A PIXEL OF SRC
		BFINS	D4,D1{D6:D5}				;ELSE REPLACE PIXEL

		ADD.L	D5,D6						;ADVANCE TO NEXT DST PIXEL
		AND		D7,D6						;TIME FOR NEXT DST LONG?
		BNE.S	@NXTDST						;=>NO
		MOVE.L	D1,(A1)+					;ELSE SAVE CURRENT DST LONG
		MOVEQ	#0,D1						;INIT DST LONG TO 0
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTDST						;=>NO, COPY NEXT SRC TO NEXT DST
		MOVEM.L	(SP)+,D6/D7					;RESTORE WORK REGISTERS
		RTS

	ELSE

	ALIGN 	Alignment

	;32 bit deep pixels ÑÑ do full color pixel averaging:

;			D0.L = src data			A0.L = ptr to src scan
;			D1.L = dst data			A1.L = ptr to dst scan
;			D2.W = ratio < 1.0		A2.L = limit ptr
;			D3.W = error term		A3.L = red accum
;			D4.W = src pix cnt		A4.L = grn accum
;			D5.L = scratch			A5.L = blu accum
;			D6.L = preserved		A6 = locals
;			D7.L = preserved		A7 = stack

AverageH32
		MOVEM.L	D5/A5,-(SP)					;SAVE WORK REGISTERS
		MOVE	D4,D2						;GET RATIO IN D2
		MOVE	D4,D3						;COPY RATIO
		LSR 	#1,D3						;INIT ERR TO RATIO/2
		cmp.w	#16,d5						;16 bits/pixel?		<KON 2/22/90>
		beq.s	averageH16					;yes, average		<KON 2/22/90>

		MOVEQ	#0,D5						;clear out working register
		move.l	d5,a3						;clear out working register			<29AUG90 KON>
		bra.s	@NXTDST						; enter the loop					<1.7>

@1to1	MOVE.L	(A0)+,(A1)+					;copy source to dest				<1.7>
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?				<1.7>
		bhs.s	HShrinkDone					;=>yes, all done					<1.7>
@NXTDST	add.w	D2,D3						;is mapping 1 to 1?					<1.7>
		bcs.s	@1to1	 					;if so, just copy the pixel			<1.7>

		MOVE.L	(A0)+,D0					;GET A PIXEL OF SRC					<1.7>
		move.b	d0,d5						;get blue component					<1.7>
		move.w	d5,a5						;INIT accumulated blu				<1.7>
		lsr.w	#8,d0						;get green component				<1.7>
		move.w	d0,a4						;INIT accumulated grn				<1.7>
		swap	d0							;get red component					<1.7>
		move.b	d0,d5						;extend to word						<1.7>
		move.w	d5,a3						;INIT accumulated red				<1.7>
		moveq	#1,d4						;init src pixel count				<1.7>

@NXTSRC	MOVE.L	(A0)+,D0					;GET A PIXEL OF SRC
		addq.w	#1,d4						;inc cnt of src pixels for this dst
		move.b	d0,d5						;extend to word
		add.w	d5,a5						;accumulate blue component
		lsr.w	#8,d0						;toss blue component
		add.w	d0,a4						;accumulate green component
		swap	d0							;toss green component
		move.b	d0,d5						;extend to word
		add.w	d5,a3						;accumulate red component

		ADD		D2,D3						;TIME FOR NEXT DST PIXEL?
		BCC.S	@NXTSRC	 					;NO, GET NEXT SRC PIXEL

		cmp.w	#2,d4						;how many pixels are being averaged?
		blt.s	@noDiv						;only one src pixel so skip divides
		beq.s	@doShift					;two src pixels so use shifts

@hardWay
		moveq	#0,d1						;clear out dst pixel
		move.l	a3,d0						;get red total
		divu.w	d4,d0						;get red avrg
		move.b	d0,d1						;save result
		lsl.l	#8,d1						;make room for next component
		move.l	a4,d0						;get grn total
		divu.w	d4,d0						;get grn avrg
		move.b	d0,d1						;save result
		lsl.l	#8,d1						;make room for next component
		move.l	a5,d0						;get blu total
		divu.w	d4,d0						;get blu avrg
		move.b	d0,d1						;save result
		bra.s	@noDiv

@doShift
		move.l	a3,d1						;get red total, clear out dst pixel			<1.7>
		lsl.w	#7,d1						;get red avrg, make room for next component	<1.7>
		move.l	a4,d0						;get grn total
		lsr.w	#1,d0						;get grn avrg								<1.7>
		move.b	d0,d1						;save result
		lsl.l	#8,d1						;make room for next component				<1.7>
		move.l	a5,d0						;get blu total
		lsr.w	#1,d0						;get blu avrg
		move.b	d0,d1						;save result

@noDiv
		MOVE.L	D1,(A1)+					;ELSE SAVE CURRENT DST LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTDST						;=>NO, COPY NEXT SRC TO NEXT DST
HShrinkDone
		MOVEM.L	(SP)+,D5/A5					;RESTORE WORK REGISTERS
		RTS

;------------16 bit average <KON 2/22/90> -----------------------
;
;16 bit deep pixels ÑÑ do full color pixel averaging:

;			D0.L = src data			A0.L = ptr to src scan
;			D1.L = dst data			A1.L = ptr to dst scan
;			D2.W = ratio < 1.0		A2.L = limit ptr
;			D3.W = error term		A3.L = red accum
;			D4.W = src pix cnt		A4.L = grn accum
;			D5.L = scratch			A5.L = blu accum
;			D6.L = preserved		A6 = locals
;			D7.L = preserved		A7 = stack

;Êfrom QDciPatchROM.a verbatim (except for commented-out stack stuff)		<sm 6/9/92>stb

;		MOVEM.L	D5/A5,-(SP)					;SAVE WORK REGISTERS (saved above in 32-bit case)
;		MOVE	D4,D2						;GET RATIO IN D2	(done in 32-bit case above)
;		MOVE	D4,D3						;COPY RATIO			(done in 32-bit case above)
;		LSR 	#1,D3						;INIT ERR TO RATIO/2	(done in 32-bit case above)
AverageH16

		MOVEQ	#0,D5						;clear out working register
		bra.s	@NXTDST						; enter the loop

@1to1	MOVE.w	(A0)+,(A1)+					;copy source to dest
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		bhs.s	HShrinkDone					;=>yes, all done

@NXTDST	moveq	#0,d0						;to extend to long
		add.w	D2,D3						;is mapping 1 to 1?
		bcs.s	@1to1	 					;if so, just copy the pixel

		MOVE.w	(A0)+,D0					;GET a PIXEL OF SRC
		move.b	d0,d5						;get blue component
		and.b	#$1F,d5
		move.w	d5,a5						;INIT accumulated blu

		lsr.w	#5,d0						;get green component
		move.b	d0,d5						;INIT accumulated grn
		and.b	#$1F,d5
		move.w	d5,a4

		lsr.w	#5,d0						;get red component
		and.b	#$1F,d0						;extend to word
		move.w	d0,a3						;INIT accumulated red
		moveq	#1,d4						;init src pixel count

@NXTSRC	MOVE.w	(A0)+,D0					;GET A PIXEL OF SRC
		addq.w	#1,d4						;inc cnt of src pixels for this dst
		move.b	d0,d5						;extend to word
		and.b	#$1F,d5						;5-bits of blue
		add.w	d5,a5						;accumulate blue component

		lsr.w	#5,d0						;toss blue component
		move.b	d0,d5
		and.b	#$1F,d5
		add.w	d5,a4						;accumulate green component

		lsr.w	#5,d0						;toss green component
		and.b	#$1F,d0						;extend to word
		add.w	d0,a3						;accumulate red component

		ADD		D2,D3						;TIME FOR NEXT DST PIXEL?
		BCC.S	@NXTSRC	 					;NO, GET NEXT SRC PIXEL

		cmp.w	#2,d4						;how many pixels are being averaged?
;		blt.s	@noDiv						;Can't Happen ;;only one src pixel so skip divides
		beq.s	@doShift					;two src pixels so use shifts

@hardWay
		moveq	#0,d1						;clear out dst pixel
		move.l	a3,d0						;get red total
		divu.w	d4,d0						;get red avrg
		move.b	d0,d1						;save result

		lsl.l	#5,d1						;make room for next component
		move.l	a4,d0						;get grn total
		divu.w	d4,d0						;get grn avrg
		or.b	d0,d1						;save result

		lsl.l	#5,d1						;make room for next component
		move.l	a5,d0						;get blu total
		divu.w	d4,d0						;get blu avrg
		or.b	d0,d1						;save result
		bra.s	@noDiv

@doShift
		move.l	a3,d1						;get red total, clear out dst pixel			<1.7>
		and.w	#$003E,d1					;only want 5 bits.
		lsl.w	#4,d1						;get red avrg, make room for next component	<1.7>
		move.l	a4,d0						;get grn total
		lsr.w	#1,d0						;get grn avrg								<1.7>
		or.b	d0,d1						;save result
		lsl.l	#5,d1						;make room for next component				<1.7>
		move.l	a5,d0						;get blu total
		lsr.w	#1,d0						;get blu avrg
		or.b	d0,d1						;save result

@noDiv
		MOVE.w	D1,(A1)+					;ELSE SAVE CURRENT DST word
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTDST						;=>NO, COPY NEXT SRC TO NEXT DST
		bra.s	HShrinkDone
;@done	MOVEM.L	(SP)+,D5/A5					;RESTORE WORK REGISTERS
;		RTS

NOAVRG


	ALIGN 	Alignment

;------------------------------------------------------------------
;
;  DO FULL-RATIO COLOR SCALING, SHRINKING ONE PIXEL AT A TIME
;

;			D0.L = src data			A0.L = ptr to src scan
;			D1.L = dst data			A1.L = ptr to dst scan
;			D2.L = src offset		A2.L = limit ptr
;			D3.W = error term		A3.W = ratio < 1.0
;			D4.L = scratch			A4 = scratch
;			D5.W = bits/pixel		A5 = scratch
;			D6.L = dst offset		A6 = locals
;			D7.L = long mask		A7 = stack

PIXSHRNK

	;	tst.b	useAverage(a6)				;use area averaging?
		cmp.w	#16,d5						;32 bits/pixel?
		bge.s	averageH32					;yes, average pixels
	ENDIF

		MOVEM.L	D6/D7,-(SP)					;SAVE WORK REGISTERS
		MOVE	D4,A3						;GET RATIO IN A3
		MOVE	D4,D3						;COPY RATIO
		LSR 	#1,D3						;INIT ERR TO RATIO/2
		MOVEQ	#0,D2						;INIT OFFSET INTO SRC
		MOVEQ	#0,D6						;INIT OFFSET INTO DST
		MOVEQ	#$1F,D7						;GET MASK FOR LONGS
		EXT.L	D5							;MAKE SURE D5 IS LONG
		MOVE.L	(A0)+,D0					;GET FIRST SRC LONG
		MOVEQ	#0,D1						;INIT FIRST DST LONG TO 0
NXTDST	SUB.L	A4,A4						;INIT DST PIXEL VALUE TO 0
NXTSRC	BFEXTU	D0{D2:D5},D4				;GET A PIXEL OF SRC
		CMP.L	A4,D4						;COMPARE AGAINST DST
		BLS.S	ADVSRC						;IF SRC < DST, DON'T REPLACE
		BFINS	D4,D1{D6:D5}				;ELSE REPLACE PIXEL
		MOVE.L	D4,A4						;AND SAVE AS DST CONTENTS
ADVSRC	ADD.L	D5,D2						;BUMP TO NEXT SRC PIXEL
		AND		D7,D2						;TIME FOR NEXT SRC LONG?
		BNE.S	@0							;=>NO
		MOVE.L	(A0)+,D0					;ELSE GET NEXT SRC LONG
@0		ADD		A3,D3						;TIME FOR NEXT DST PIXEL?
		BCC.S	NXTSRC	 					;NO, GET NEXT SRC PIXEL
		ADD.L	D5,D6						;ADVANCE TO NEXT DST PIXEL
		AND		D7,D6						;TIME FOR NEXT DST LONG?
		BNE.S	NXTDST						;=>NO
		MOVE.L	D1,(A1)+					;ELSE SAVE CURRENT DST LONG
		MOVEQ	#0,D1						;INIT DST LONG TO 0
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	NXTDST						;=>NO, COPY NEXT SRC TO NEXT DST
		MOVEM.L	(SP)+,D6/D7					;RESTORE WORK REGISTERS
		RTS


	ALIGN 	Alignment

;------------------------------------------------------------------
;
;  DO FULL-RATIO COLOR SCALING, STRETCHING ONE PIXEL AT A TIME
;
PIXSTR	MOVEM.L	D6/D7,-(SP)					;SAVE WORK REGISTERS
		MOVE	D4,A3						;GET RATIO IN A3
		MOVE	D4,D3						;COPY RATIO
		LSR 	#1,D3						;INIT ERR TO RATIO/2
		MOVEQ	#0,D2						;INIT OFFSET INTO SRC
		MOVEQ	#0,D6						;INIT OFFSET INTO DST
		MOVEQ	#$1F,D7						;GET MASK FOR LONGS
		EXT.L	D5							;MAKE SURE D5 IS LONG
NXTSRC3 MOVE.L	(A0)+,D0					;GET FIRST LONG OF SRC
NXTSRC4	BFEXTU	D0{D2:D5},D4				;GET A PIXEL OF SRC
NXTDST1	BFINS	D4,D1{D6:D5}				;PUT TO DST LONG
		ADD.L	D5,D6						;BUMP TO NEXT DST PIXEL
		AND		D7,D6						;TIME FOR NEXT DST LONG?
		BNE.S	@0							;=>NO
		MOVE.L	D1,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BHS.S	DONESTR						;=>YES, RETURN
@0		ADD.W	A3,D3						;TIME FOR NEXT SRC PIXEL?
		BCC.S	NXTDST1	 					;=>NO, PUT NEXT DST PIXEL
		ADD.L	D5,D2						;ADVANCE TO NEXT SRC PIXEL
		AND		D7,D2						;TIME FOR NEXT SRC LONG?
		BNE.S	NXTSRC4						;=>NO, GET NEXT SRC PIXEL
		BRA.S	NXTSRC3						;=>ELSE GET NEXT SRC LONG
DONESTR	MOVEM.L	(SP)+,D6/D7					;RESTORE WORK REGISTERS
		RTS



ScaleIndexedToIndexed	PROC	EXPORT
;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM ONE DEPTH TO ANOTHER
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	D6/D7,-(SP)					;SAVE WORK REGISTERS
		MOVEQ	#0,D1						;INIT OFFSET INTO SRC
		MOVEQ	#0,D2						;INIT OFFSET INTO DST
		MOVEQ	#$1F,D7						;GET MASK FOR LONGS
		BRA.S	NXTSLNG

NXTDPXL	ADD		D3,D1						;ADVANCE TO NEXT SRC PIXEL
		AND		D7,D1						;TIME FOR NEXT SRC LONG?
		BNE.S	NXTSPXL						;ELSE GET NEXT PIXEL
NXTSLNG MOVE.L	(A0)+,D5					;GET FIRST LONG OF SRC
NXTSPXL	BFEXTU	D5{D1:D3},D0				;GET A PIXEL OF SRC
		move.l	0(A4,D0*4),D0				;TRANSLATE IT				<BAL 09May88> @@@@
		BFINS	D0,D6{D2:D4}				;PUT TO DST LONG
		ADD		D4,D2						;BUMP TO NEXT DST PIXEL
		AND		D7,D2						;TIME FOR NEXT DST LONG?
		BNE.S	NXTDPXL						;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	NXTDPXL						;=>YES, RETURN
DONESCL	MOVEM.L	(SP)+,D6/D7					;RESTORE WORK REGISTERS
		RTS


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Dither32toIndexed	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;

		MOVEM.L	A3/A5/D6/D7,-(SP)				;SAVE WORK REGISTERS

		MOVE.L	ErrBuf(a6),A4				;get ptr to ErrBuf
		MOVEQ	#0,D2						;INIT OFFSET INTO DST
		MOVE.L	D2,D5						;init redAccum
		MOVE.L	D2,D6						;init grnAccum
		MOVE.L	D2,D7						;init bluAccum
		not.b	errDir(a6)					;check and toggle diffusion direction
		bne.s	@forward

		move.l	ErrSrcBuf(a6),a0			;point to end of srcBuf
		moveq	#32,d2						;init dst offset in long

@back2
		sub.w	D4,D2						;pre-BUMP TO NEXT DST PIXEL
@backward 
		sub.w	#6,a4
		MOVE.L	-(A0),D0					;GET NEXT LONG OF SRC
		bsr.s	ditherCore

		moveq	#0,d3
		asr.w	#1,d5						;get half red error
		move.w	d5,0(a4)					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d5
		asr.w	#1,d6						;get half grn error
		move.w	d6,2(a4)					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d6
		asr.w	#1,d7						;get half blu error
		move.w	d7,4(a4)					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7

		sub.w	D4,D2						;BUMP TO NEXT DST PIXEL
		bge.s	@backward					;TIME FOR NEXT DST LONG? =>NO
		moveq	#32,d2
		MOVE.L	D1,-(A2)					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@back2						;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		bra.s	donescl

@forward 
		MOVE.L	(A0)+,D0					;GET NEXT LONG OF SRC
		bsr.s	ditherCore

		moveq	#0,d3
		asr.w	#1,d5						;get half red error
		move.w	d5,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d5
		asr.w	#1,d6						;get half grn error
		move.w	d6,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d6
		asr.w	#1,d7						;get half blu error
		move.w	d7,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7

@again
		ADD		D4,D2						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D2						;TIME FOR NEXT DST LONG?
		BNE.S	@forward					;=>NO
		MOVE.L	D1,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@forward					;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		move.l	a0,ErrSrcBuf(a6)			;point to end of srcBuf for right to left diffusion

DONESCL
		MOVEM.L	(SP)+,A3/A5/D6/D7				;RESTORE WORK REGISTERS
		RTS

DitherCore
		add.w	(a4),D5						;consume red error from above
		add.w	2(a4),D6					;consume grn error from above
		add.w	4(a4),D7					;consume blu error from above
		moveq	#0,d3						;clear out temp

		move.b	d0,d3						;get blue as a word
		add.w	d3,d7						;accumulate blue
		lsr.w	#8,d0						;toss blue

		add.w	d0,d6						;accumulate green
		swap	d0							;toss green

		move.b	d0,d3						;get red as a word
		add.w	d3,d5						;accumulate red

		swap	d4							;save dst pixel size in high word
		move.w	stITabRes(A6),D0			;get the iTable resolution

		tst.w	d5							;get desired red
		spl		d3							;get pin value if neg
		cmp.w	d3,d5						;is it too big
		sgt		d4							;get pin value if too big
		and.b	d5,d3						;pin to zero
		or.b	d4,d3						;pin to 255

		moveq	#0,d5
		move.b	d3,d5

		lsl.l	d0,d3						;move it up

		tst.w	d6							;get desired green
		spl		d3							;get pin value if neg
		cmp.w	#$ff,d6						;is it too big
		sgt		d4							;get pin value if too big
		and.b	d6,d3						;pin to zero
		or.b	d4,d3						;pin to 255

		moveq	#0,d6
		move.b	d3,d6

		lsl.l	d0,d3						;move it up

		tst.w	d7							;get desired blue
		spl		d3							;get pin value if neg
		cmp.w	#$ff,d7						;is it too big
		sgt		d4							;get pin value if too big
		and.b	d7,d3						;pin to zero
		or.b	d4,d3						;pin to 255
		neg		d0
		addq	#8,d0

		moveq	#0,d7
		move.b	d3,d7

		lsr.l	d0,d3						;throw out the insignificant bits

		swap	d4							;get back dst pixel size
		moveq	#0,d0						;clear out high end
		MOVE.L	stITabPtr(A6),A3			;get pointer to the inverse table (past header)
		move.b	(a3,d3.L),d0				;get the index in D0 (hi 3 bytes still clear)

		BFINS	D0,D1{D2:D4}				;PUT TO DST LONG
		MOVE.L	stCLUTPtr(a6),A3			;get clut ptr
		lea		CTTable+rgb+red(A3,D0.L*8),a5	;point at red value
		move.l	(a5)+,d3					;get RRRRGGGG							<05JUNE92 SAH>
		
		lsr.l	#8,d3						;get high byte of green					<05JUNE92 SAH>
		move.b	d3,d0						;make it a word (hi 3 bytes d0 clear)	<05JUNE92 SAH>
		sub.w	d0,d6						;compute green error					<05JUNE92 SAH>

		swap	d3							;get high byte of red					<05JUNE92 SAH>
		sub.w	d3,d5						;compute red error						<05JUNE92 SAH>

		move.b	(a5)+,d0					;get high byte of blue					<05JUNE92 SAH>
		sub.w	d0,d7						;compute blue error						<05JUNE92 SAH>
		
		rts



Dither16toIndexed	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;

		MOVEM.L	A3/A5/D6/D7,-(SP)				;SAVE WORK REGISTERS

@1		MOVE.L	ErrBuf(a6),A4				;get ptr to ErrBuf
		MOVEQ	#0,D2						;INIT OFFSET INTO DST
		MOVE.L	D2,D5						;init redAccum
		MOVE.L	D2,D6						;init grnAccum
		MOVE.L	D2,D7						;init bluAccum
		moveq	#0,d3
		not.b	errDir(a6)					;check and toggle diffusion direction
		bne.s	@forward

		move.l	ErrSrcBuf(a6),a0			;point to end of srcBuf
		moveq	#32,d2						;init dst offset in long

@back2
		sub.w	D4,D2						;pre-BUMP TO NEXT DST PIXEL
@backward 
		sub.w	#6,a4
		MOVE.w	-(A0),D0					;GET NEXT word OF SRC
		bsr.s	ditherCore

		moveq	#0,d3
		asr.w	#1,d5						;get half red error
		move.w	d5,0(a4)					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d5
		asr.w	#1,d6						;get half grn error
		move.w	d6,2(a4)					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d6
		asr.w	#1,d7						;get half blu error
		move.w	d7,4(a4)					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7

		sub.w	D4,D2						;BUMP TO NEXT DST PIXEL
		bge.s	@backward					;TIME FOR NEXT DST LONG? =>NO
		moveq	#32,d2
		MOVE.L	D1,-(A2)					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@back2						;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		bra.s	donescl

@forward 
		MOVE.w	(A0)+,D0					;GET NEXT LONG OF SRC
		bsr.s	ditherCore

		moveq	#0,d3
		asr.w	#1,d5						;get half red error
		move.w	d5,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d5
		asr.w	#1,d6						;get half grn error
		move.w	d6,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d6
		asr.w	#1,d7						;get half blu error
		move.w	d7,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7

@again
		ADD		D4,D2						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D2						;TIME FOR NEXT DST LONG?
		BNE.S	@forward					;=>NO
		MOVE.L	D1,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@forward					;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		move.l	a0,ErrSrcBuf(a6)			;point to end of srcBuf for right to left diffusion

DONESCL
		MOVEM.L	(SP)+,A3/A5/D6/D7				;RESTORE WORK REGISTERS
		RTS

DitherCore
		add.w	(a4),D5						;consume red error from above
		add.w	2(a4),D6					;consume grn error from above
		add.w	4(a4),D7					;consume blu error from above
	;	moveq	#0,d3						;clear out temp ;cleared on entry
		swap	d4							;save dst pixel size in high word

		move.b	d0,d3						;get blue as a word
		lsl.b	#3,d3						;left justify 5 bits
		move.b	d3,d4
		lsr.b	#5,d4						;right justify high 3 bits
		or.b	d4,d3						;replicate into 8 bits
		add.w	d3,d7						;accumulate blue
		lsr.l	#5,d0						;toss blue

		move.b	d0,d3						;get green as a word
		lsl.b	#3,d3						;left justify 5 bits
		move.b	d3,d4
		lsr.b	#5,d4						;right justify high 3 bits
		or.b	d4,d3						;replicate into 8 bits
		add.w	d3,d6						;accumulate green
		lsr.l	#5,d0						;toss green

		move.b	d0,d3						;get red as a word
		lsl.b	#3,d3						;left justify 5 bits
		move.b	d3,d4
		lsr.b	#5,d4						;right justify high 3 bits
		or.b	d4,d3						;replicate into 8 bits
		add.w	d3,d5						;accumulate red

		move.w	stITabRes(A6),D0			;get the iTable resolution

		tst.w	d5							;get desired red
		spl		d3							;get pin value if neg
		cmp.w	d3,d5						;is it too big
		sgt		d4							;get pin value if too big
		and.b	d5,d3						;pin to zero
		or.b	d4,d3						;pin to 255

		moveq	#0,d5
		move.b	d3,d5

		lsl.l	d0,d3						;move it up

		tst.w	d6							;get desired green
		spl		d3							;get pin value if neg
		cmp.w	#$ff,d6						;is it too big
		sgt		d4							;get pin value if too big
		and.b	d6,d3						;pin to zero
		or.b	d4,d3						;pin to 255

		moveq	#0,d6
		move.b	d3,d6

		lsl.l	d0,d3						;move it up

		tst.w	d7							;get desired blue
		spl		d3							;get pin value if neg
		cmp.w	#$ff,d7						;is it too big
		sgt		d4							;get pin value if too big
		and.b	d7,d3						;pin to zero
		or.b	d4,d3						;pin to 255
		neg		d0
		addq	#8,d0

		moveq	#0,d7
		move.b	d3,d7

		lsr.l	d0,d3						;throw out the insignificant bits

		swap	d4							;get back dst pixel size
		moveq	#0,d0						;clear out high end
		MOVE.L	stITabPtr(A6),A3			;get pointer to the inverse table (past header)
		move.b	(a3,d3.L),d0				;get the index in D0 (hi 3 bytes still clear)
		BFINS	D0,D1{D2:D4}				;PUT TO DST LONG
		MOVE.L	stCLUTPtr(a6),A3			;get clut ptr
		lea		CTTable+rgb+red(A3,D0.L*8),a5	;point at red value
		move.l	(a5)+,d0					;get RRRRGGGG

		moveq	#0,d3						;clear out high end
		lsr.l	#8,d0						;get high byte of green
		move.b	d0,d3						;make it a word
		sub.w	d3,d6						;compute green error

		swap	d0							;get high byte of red
		move.b	d0,d3						;make it a word
		sub.w	d3,d5						;compute red error

		move.w	(a5),d0						;get BBBBxxxx
		lsr.w	#8,d0						;get high byte of blue
		move.b	d0,d3						;make it a word
		sub.w	d3,d7						;compute blue error

		rts
		ENDPROC

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Dither32toGray	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


		MACRO
		_DitherGray

		move.b	d3,d2						; get the blue component
		lsr.l	#8,d3						; get red,green in low word
		move.b	d3,d1						; get the green component
		lsr.w	#8,d3						; get red in low byte
		move.b	d3,d0						; get the red component

; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3

		add.w	d3,d7						; consume error from right (or left)
		add.w	(a4),d7						; consume error from above
		spl		d2							; get pin value if neg
		cmp.w	d2,d7						; is it too big
		sgt		d1							; get pin value if too big
		and.b	d2,d7						; pin to zero
		or.b	d1,d7						; pin to 255
		move.b	d7,d1						; extend to a word

		move.b	(a3,d1),d0					; pick up index for this luminance
		BFINS	D0,D6{D5:D4}				; PUT TO DST LONG
		move.w	d1,d7						; get requested luminance as a word		<BAL 30Jan90>
		move.b	(a5,d1),d1					; get actual luminance as a word		<BAL 30Jan90>
		sub.w	d1,d7						; get luminance error as a word			<BAL 30Jan90>

		ENDM

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6/D7,-(SP)				;SAVE WORK REGISTERS

		MOVE.L	stITabInfo(A6),A3			;get pointer to the luminance table (past header)
		lea		ITabLuma-ITabInfo(a3),a5	;point to luma table

@1		MOVE.L	ErrBuf(a6),A4				;get ptr to ErrBuf
		MOVEQ	#0,D5						;INIT OFFSET INTO DST
		MOVE.L	D5,D0						;clear high end
		MOVE.L	D5,D1						;clear high end
		MOVE.L	D5,D2						;clear high end
		not.b	errDir(a6)					;check and toggle diffusion direction
		bne.s	@forward

		move.l	ErrSrcBuf(a6),a0			;point to end of srcBuf
		moveq	#32,d5						;init dst offset in long

@back2
		sub.w	D4,D5						;pre-BUMP TO NEXT DST PIXEL
@backward 
		sub.w	#2,a4
		MOVE.L	-(A0),D3					;GET NEXT LONG OF SRC
		_DitherGray

		moveq	#0,d3						;									<23Feb90 KON>
		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)						;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7						;prevent error from accumulating	<23Feb90 KON>

		sub.w	D4,D5						;BUMP TO NEXT DST PIXEL
		bge.s	@backward					;TIME FOR NEXT DST LONG? =>NO
		moveq	#32,d5
		MOVE.L	D6,-(A2)					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@back2						;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		bra.s	@donescl

@forward 
		MOVE.L	(A0)+,D3					;GET NEXT LONG OF SRC
		_DitherGray

		moveq	#0,d3						;									<23Feb90 KON>
		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7						;prevent error from accumulating	<23Feb90 KON>

		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@forward					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@forward					;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		move.l	a0,ErrSrcBuf(a6)			;point to end of srcBuf for right to left diffusion

@DONESCL
		MOVEM.L	(SP)+,A3/A5/D6/D7				;RESTORE WORK REGISTERS
		RTS
		ENDPROC


Dither32toBitmap	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


		MACRO
		_DitherBitmap32

		move.b	d3,d2						; get the blue component
		lsr.l	#8,d3						; get red,green in low word
		move.b	d3,d1						; get the green component
		lsr.w	#8,d3						; get red in low byte
		move.b	d3,d0						; get the red component

; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3

		add.w	d3,d7						; consume error from right (or left)
		add.w	(a4),d7						; consume error from above
		spl		d2							; get pin value if neg
		cmp.w	d2,d7						; is it too big
		sgt		d1							; get pin value if too big
		and.b	d2,d7						; pin to zero
		or.b	d1,d7						; pin to 255
		move.b	d7,d1						; extend to a word

		spl		d0							; ³$80 -> $00; <$80 -> $ff
		BFINS	D0,D6{D5:D4}				; PUT TO DST LONG
		not.b	d0							; get luminance value of output pixel as a word
		move.w	d1,d7						; get requested luminance as a word		<BAL 30Jan90>
		sub.w	d0,d7						; get luminance error as a word			<BAL 30Jan90>

		ENDM

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	D6/D7,-(SP)				;SAVE WORK REGISTERS

@1		MOVE.L	ErrBuf(a6),A4				;get ptr to ErrBuf
		MOVEQ	#0,D5						;INIT OFFSET INTO DST
		MOVE.L	D5,D0						;clear high end
		MOVE.L	D5,D1						;clear high end
		MOVE.L	D5,D2						;clear high end
		not.b	errDir(a6)					;check and toggle diffusion direction
		bne.s	@forward

		move.l	ErrSrcBuf(a6),a0			;point to end of srcBuf
		moveq	#32,d5						;init dst offset in long

@back2
		sub.w	D4,D5						;pre-BUMP TO NEXT DST PIXEL
@backward 
		sub.w	#2,a4
		MOVE.L	-(A0),D3					;GET NEXT LONG OF SRC
		_DitherBitmap32

		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)						;save 1/2 for next scanline and carry 1/2 to right

		sub.w	D4,D5						;BUMP TO NEXT DST PIXEL
		bge.s	@backward					;TIME FOR NEXT DST LONG? =>NO
		moveq	#32,d5
		MOVE.L	D6,-(A2)					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@back2						;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		bra.s	@donescl

@forward 
		MOVE.L	(A0)+,D3					;GET NEXT LONG OF SRC
		_DitherBitmap32

		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)+					;save 1/2 for next scanline and carry 1/2 to right

		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@forward					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@forward					;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		move.l	a0,ErrSrcBuf(a6)			;point to end of srcBuf for right to left diffusion

@DONESCL
		MOVEM.L	(SP)+,D6/D7				;RESTORE WORK REGISTERS
		RTS

		ENDPROC

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Dither16toGray	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


		MACRO
		_DitherGray16

		lsl.l	#3,d3						; left justify lo 5 bits
		move.b	d3,d2						; get the blue component
		lsl.w	#5,d2						; save 5 bits
		move.b	d3,d2						; get 5 more bits
		lsr.w	#5,d2						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d1						; get 5 of the green bits
		lsl.w	#5,d1						; save 5 bits
		move.b	d3,d1						; get 5 more bits
		lsr.w	#5,d1						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d0						; get 5 of the red bits
		lsl.w	#5,d0						; save 5 bits
		move.b	d3,d0						; get 5 more bits
		lsr.w	#5,d0						; chuck 2 of the ten
		move.w	d0,d3						; make a copy of the red


; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3

		add.w	d3,d7						; consume error from right (or left)
		add.w	(a4),d7						; consume error from above
		spl		d2							; get pin value if neg
		cmp.w	d2,d7						; is it too big
		sgt		d1							; get pin value if too big
		and.b	d2,d7						; pin to zero
		or.b	d1,d7						; pin to 255
		move.b	d7,d1						; extend to a word

		move.b	(a3,d1),d0					; pick up index for this luminance
		BFINS	D0,D6{D5:D4}				; PUT TO DST LONG
		move.w	d1,d7						; get requested luminance as a word		<BAL 30Jan90>
		move.b	(a5,d1),d1					; get actual luminance as a word		<BAL 30Jan90>
		sub.w	d1,d7						; get luminance error as a word			<BAL 30Jan90>

		ENDM

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6/D7,-(SP)				;SAVE WORK REGISTERS

		moveq	#0,d3						;clear out high word
		MOVE.L	stITabInfo(A6),A3			;get pointer to the luminance table (past header)
		lea		ITabLuma-ITabInfo(a3),a5	;point to luma table

@1		MOVE.L	ErrBuf(a6),A4				;get ptr to ErrBuf
		MOVEQ	#0,D5						;INIT OFFSET INTO DST
		MOVE.L	D5,D0						;clear high end
		MOVE.L	D5,D1						;clear high end
		MOVE.L	D5,D2						;clear high end
		not.b	errDir(a6)					;check and toggle diffusion direction
		bne.s	@forward

		move.l	ErrSrcBuf(a6),a0			;point to end of srcBuf
		moveq	#32,d5						;init dst offset in long

@back2
		sub.w	D4,D5						;pre-BUMP TO NEXT DST PIXEL
@backward 
		sub.w	#2,a4
		MOVE.w	-(A0),D3					;GET NEXT LONG OF SRC
		_DitherGray16

		moveq	#0,d3						;									<23Feb90 KON>
		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)						;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7						;prevent error from accumulating	<23Feb90 KON>

		sub.w	D4,D5						;BUMP TO NEXT DST PIXEL
		bge.s	@backward					;TIME FOR NEXT DST LONG? =>NO
		moveq	#32,d5
		MOVE.L	D6,-(A2)					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@back2						;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		bra.s	@donescl

@forward 
		MOVE.w	(A0)+,D3					;GET NEXT LONG OF SRC
		_DitherGray16

		moveq	#0,d3						;									<23Feb90 KON>
		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)+					;save 1/2 for next scanline and carry 1/2 to right
		addx.w	d3,d7						;prevent error from accumulating	<23Feb90 KON>

		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@forward					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@forward					;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		move.l	a0,ErrSrcBuf(a6)			;point to end of srcBuf for right to left diffusion

@DONESCL
		MOVEM.L	(SP)+,A3/A5/D6/D7				;RESTORE WORK REGISTERS
		RTS

		ENDPROC


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Dither16toBitmap	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


		MACRO
		_DitherBitmap16

		lsl.l	#3,d3						; left justify lo 5 bits
		move.b	d3,d2						; get the blue component
		lsl.w	#5,d2						; save 5 bits
		move.b	d3,d2						; get 5 more bits
		lsr.w	#5,d2						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d1						; get 5 of the green bits
		lsl.w	#5,d1						; save 5 bits
		move.b	d3,d1						; get 5 more bits
		lsr.w	#5,d1						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d0						; get 5 of the red bits
		lsl.w	#5,d0						; save 5 bits
		move.b	d3,d0						; get 5 more bits
		lsr.w	#5,d0						; chuck 2 of the ten
		move.w	d0,d3						; make a copy of the red


; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3

		add.w	d3,d7						; consume error from right (or left)
		add.w	(a4),d7						; consume error from above
		spl		d2							; get pin value if neg
		cmp.w	d2,d7						; is it too big
		sgt		d1							; get pin value if too big
		and.b	d2,d7						; pin to zero
		or.b	d1,d7						; pin to 255
		move.b	d7,d1						; extend to a word

		spl		d0							; ³$80 -> $00; <$80 -> $ff
		BFINS	D0,D6{D5:D4}				; PUT TO DST LONG
		not.b	d0							; get luminance value of output pixel as a word
		move.w	d1,d7						; get requested luminance as a word		<BAL 30Jan90>
		sub.w	d0,d7						; get luminance error as a word			<BAL 30Jan90>

		ENDM

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	D6/D7,-(SP)				;SAVE WORK REGISTERS

		moveq	#0,d3						;clear out high word

@1		MOVE.L	ErrBuf(a6),A4				;get ptr to ErrBuf
		MOVEQ	#0,D5						;INIT OFFSET INTO DST
		MOVE.L	D5,D0						;clear high end
		MOVE.L	D5,D1						;clear high end
		MOVE.L	D5,D2						;clear high end
		not.b	errDir(a6)					;check and toggle diffusion direction
		bne.s	@forward

		move.l	ErrSrcBuf(a6),a0			;point to end of srcBuf
		moveq	#32,d5						;init dst offset in long

@back2
		sub.w	D4,D5						;pre-BUMP TO NEXT DST PIXEL
@backward 
		sub.w	#2,a4
		MOVE.w	-(A0),D3					;GET NEXT LONG OF SRC
		_DitherBitmap16

		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)						;save 1/2 for next scanline and carry 1/2 to right

		sub.w	D4,D5						;BUMP TO NEXT DST PIXEL
		bge.s	@backward					;TIME FOR NEXT DST LONG? =>NO
		moveq	#32,d5
		MOVE.L	D6,-(A2)					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@back2						;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		bra.s	@donescl

@forward 
		MOVE.w	(A0)+,D3					;GET NEXT LONG OF SRC
		_DitherBitmap16

		asr.w	#1,d7						;get half error (signed)
		move.w	d7,(a4)+					;save 1/2 for next scanline and carry 1/2 to right

		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@forward					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@forward					;if lower, continue to next pixel
		move.l	a4,ErrBuf(a6)				;point to end of errBuf for right to left diffusion
		move.l	a0,ErrSrcBuf(a6)			;point to end of srcBuf for right to left diffusion

@DONESCL
		MOVEM.L	(SP)+,D6/D7				;RESTORE WORK REGISTERS
		RTS

		ENDPROC

Scale32toIndexed	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'

anyCmpSize	equ 0

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6/D7,-(SP)				;SAVE WORK REGISTERS
		MOVEQ	#0,D2						;INIT OFFSET INTO DST

		MOVE.L	stITabPtr(A6),A3			;get pointer to the inverse table (past header)
		MOVE.W	stITabRes(A6),D1			;get the iTable resolution
	;	move.w	srcCmpSize(a6),d3			;get size of each cmp
		moveq	#8,d3
		move.w	d3,d7						;
		sub.w	d1,d7						;d7 is cmp size - itabres
		move.l	(a0)+,d5					;get first long of src
		bra.s	@first
@NXTSLNG 
		MOVE.L	(A0)+,D5					;GET NEXT LONG OF SRC
		cmp.l	d5,a5						;same as last long?
		beq.s	@again						;yes, go fast
@first
		move.l	d5,a5						;save last 32 bit pixel value

;		BFEXTU	D5{8:D1},D0		;5,8,8		;extract iTabRes bits of red (clearing hi bits)
;		LSL.L	D1,D0			;3,6,6		;shift over by iTabRes
;		BFEXTU	D5{16:D1},D3	;5,8,8		;get the green component
;		OR.L	D3,D0			;0,2,3		;put them together
;		LSL.L	D1,D0			;3,6,6		;shift again
;		BFEXTU	D5{24:D1},D3	;5,8,8		;get the blue component
;		OR.L	D3,D0			;0,2,3		;put them together to form iTable index
								;21,40,42

	if anyCmpSize then

		lsr.l	d7,d5	;3,6,6				;normalize data by trashing extra bits
		move.b	d5,d0	;0,2,3				;get blue
		ror.l	d1,d0	;5,8,8				;save itabres bits of blue in high word
		lsr.l	d3,d5	;3,6,6				;chuck blue and get green cmp
		move.b	d5,d0	;0,2,3				;get green
		ror.l	d1,d0	;5,8,8				;save itabres bits of green in high word
		lsr.l	d3,d5	;3,6,6				;chuck green and get red cmp
		move.b	d5,d0	;0,2,3				;get red
		ror.l	d1,d0	;5,8,8				;save itabres bits of red in high word
		clr.w	d0		;0,2,3				;remove alpha bits 
		move	d1,d5	;0,2,3
		add		d5,d5	;0,2,3
		add		d1,d5	;0,2,3
		rol.l	d5,d0	;5,8,8				;rol back by 3 * itabres
						;29,64,71

	else

		moveq	#0,d0	;0,2,3				;start fresh
		move.w	d5,d3	;0,2,3				;save blue/green for later
		swap	d5		;1,4,4				;get red in low byte
		move.b	d5,d0	;0,2,3
		lsl.l	d1,d0	;3,6,6				;save itabres bits of red in high bytes
		lsr.l	#8,d3	;1,4,4				;chuck blue and get green cmp
		move.b	d3,d0	;0,2,3				;get green
		lsl.l	d1,d0	;3,6,6				;save itabres bits of green in high bytes
		swap	d5		;1,4,4				;get blue in low byte
		move.b	d5,d0	;0,2,3				;get red
		lsr.l	d7,d0	;3,6,6				;shift back by cmpsize-itabres
						;12,40,45

	endif

		MOVE.B	(A3,D0.w),D0				;get the index in D0
@again
		BFINS	D0,D6{D2:D4}				;PUT TO DST LONG
		ADD		D4,D2						;BUMP TO NEXT DST PIXEL
		AND		#$1f,D2						;TIME FOR NEXT DST LONG?
		BNE.S	@NXTSLNG					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTSLNG					;if lower, continue to next pixel
DONESCL
		MOVEM.L	(SP)+,A3/A5/D6/D7				;RESTORE WORK REGISTERS
		RTS




Scale32toGray	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6,-(SP)				;SAVE WORK REGISTERS
		MOVEQ	#0,D5						;INIT OFFSET INTO DST

		moveq	#0,d0						; clear out high end
		moveq	#0,d1						; clear out high end
		moveq	#0,d2						; clear out high end
		MOVE.L	stITabInfo(A6),A3			;get pointer to the luminance table (past header)
		move.l	(a0)+,d3					;get first long of src
		bra.s	@first
@NXTSLNG 
		MOVE.L	(A0)+,D3					;GET NEXT LONG OF SRC
		cmp.l	d3,a5						;same as last long?
		beq.s	@again						;yes, go fast
@first
		move.l	d3,a5						;save last 32 bit pixel value

		move.b	d3,d2						; get the blue component
		lsr.l	#8,d3						; get red,green in low word
		move.b	d3,d1						; get the green component
		lsr.w	#8,d3						; get red in low byte
		move.b	d3,d0						; get the red component

; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3
		move.b	(a3,d3),d0					; pick up index for this luminance
@again
		BFINS	D0,D6{D5:D4}				;PUT TO DST LONG
		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1f,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@NXTSLNG					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTSLNG					;if lower, continue to next pixel
DONESCL
		MOVEM.L	(SP)+,A3/A5/D6				;RESTORE WORK REGISTERS
		RTS


Scale32toBitMap	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO A B/W BitMap
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6,-(SP)				;SAVE WORK REGISTERS
		MOVEQ	#0,D5						;INIT OFFSET INTO DST

		moveq	#0,d0						; clear out high end
		moveq	#0,d1						; clear out high end
		moveq	#0,d2						; clear out high end
		move.l	(a0)+,d3					;get first long of src
		bra.s	@first
@NXTSLNG 
		MOVE.L	(A0)+,D3					;GET NEXT LONG OF SRC
		cmp.l	d3,a5						;same as last long?
		beq.s	@again						;yes, go fast
@first
		move.l	d3,a5						;save last 32 bit pixel value

		move.b	d3,d2						; get the blue component
		lsr.l	#8,d3						; get red,green in low word
		move.b	d3,d1						; get the green component
		lsr.w	#8,d3						; get red in low byte
		move.b	d3,d0						; get the red component

; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3

		tst.b	d3							; check high bit of luminance
		spl		d0							; put a 1 in low bit for black
@again
		BFINS	D0,D6{D5:D4}				;PUT TO DST LONG
		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1f,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@NXTSLNG					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTSLNG					;if lower, continue to next pixel
DONESCL
		MOVEM.L	(SP)+,A3/A5/D6				;RESTORE WORK REGISTERS
		RTS




Scale16toGray	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO 1-8 BIT GrayScale Clut
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6,-(SP)				;SAVE WORK REGISTERS
		MOVEQ	#0,D5						;INIT OFFSET INTO DST

		moveq	#0,d0						; clear out high end
		moveq	#0,d1						; clear out high end
		moveq	#0,d2						; clear out high end
		MOVE.L	stITabInfo(A6),A3			;get pointer to the luminance table (past header)
		move.w	(a0)+,d3					;get first long of src
		bra.s	@first
@NXTSLNG 
		MOVE.w	(A0)+,D3					;GET NEXT LONG OF SRC
		cmp.w	d3,a5						;same as last long?
		beq.s	@again						;yes, go fast
@first
		move.w	d3,a5						;save last 32 bit pixel value


		lsl.l	#3,d3						; left justify lo 5 bits
		move.b	d3,d2						; get the blue component
		lsl.w	#5,d2						; save 5 bits
		move.b	d3,d2						; get 5 more bits
		lsr.w	#5,d2						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d1						; get 5 of the green bits
		lsl.w	#5,d1						; save 5 bits
		move.b	d3,d1						; get 5 more bits
		lsr.w	#5,d1						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d0						; get 5 of the red bits
		lsl.w	#5,d0						; save 5 bits
		move.b	d3,d0						; get 5 more bits
		lsr.w	#5,d0						; chuck 2 of the ten
		move.w	d0,d3						; make a copy of the red

; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3
		move.b	(a3,d3),d0					; pick up index for this luminance
@again
		BFINS	D0,D6{D5:D4}				;PUT TO DST LONG
		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1f,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@NXTSLNG					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTSLNG					;if lower, continue to next pixel
DONESCL
		MOVEM.L	(SP)+,A3/A5/D6				;RESTORE WORK REGISTERS
		RTS



Scale16toBitMap	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO B/W BitMap
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6,-(SP)				;SAVE WORK REGISTERS
		MOVEQ	#0,D5						;INIT OFFSET INTO DST

		moveq	#0,d0						; clear out high end
		moveq	#0,d1						; clear out high end
		moveq	#0,d2						; clear out high end
		move.w	(a0)+,d3					;get first long of src
		bra.s	@first
@NXTSLNG 
		MOVE.w	(A0)+,D3					;GET NEXT LONG OF SRC
		cmp.w	d3,a5						;same as last long?
		beq.s	@again						;yes, go fast
@first
		move.w	d3,a5						;save last 32 bit pixel value


		lsl.l	#3,d3						; left justify lo 5 bits
		move.b	d3,d2						; get the blue component
		lsl.w	#5,d2						; save 5 bits
		move.b	d3,d2						; get 5 more bits
		lsr.w	#5,d2						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d1						; get 5 of the green bits
		lsl.w	#5,d1						; save 5 bits
		move.b	d3,d1						; get 5 more bits
		lsr.w	#5,d1						; chuck 2 of the ten

		lsr.l	#5,d3						; left justify lo 5 bits
		move.b	d3,d0						; get 5 of the red bits
		lsl.w	#5,d0						; save 5 bits
		move.b	d3,d0						; get 5 more bits
		lsr.w	#5,d0						; chuck 2 of the ten
		move.w	d0,d3						; make a copy of the red

; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2

		add.w	d1,d3
		add.w	d2,d3
		add.w	d2,d3
		lsr.w	#2,d3
		add.w	d0,d3
		add.w	d1,d3
		add.w	d1,d3
		lsr.w	#2,d3

		tst.b	d3							; check high bit of luminance
		spl		d0							; put a 1 in low bit for black
@again
		BFINS	D0,D6{D5:D4}				;PUT TO DST LONG
		ADD		D4,D5						;BUMP TO NEXT DST PIXEL
		AND		#$1f,D5						;TIME FOR NEXT DST LONG?
		BNE.S	@NXTSLNG					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTSLNG					;if lower, continue to next pixel
DONESCL
		MOVEM.L	(SP)+,A3/A5/D6				;RESTORE WORK REGISTERS
		RTS
		ENDPROC


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Search32to32		PROC	EXPORT			;							<20AUG90 KON>
;
; this routine draws a 32-bit direct pixel to a 32 bit destination 
;	first applying the search proc for this device, then using a direct lookup
;	if that fails.  
;
;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 16 BIT DIRECT
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3-A5/D7,-(SP)				;SAVE WORK REGISTERS
		MOVE.L	A0,A4						;copy source buffer address to non-volatile register
		MOVE.L	A1,A3						;copy dest buffer address

		move.l	saveA5(a6),a5				;set up caller's A5 for the search proc		<1.5> BAL

		moveq	#0,d0						;force 24-bit mode							<1.5>
		move.l	a2,d7						;save a2 just for grins						<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.l	d7,a2						;restore a2 just in case					<1.5>

		CLR.L	-(SP)						;make room for SearchProc result
		CLR.L	-(SP)						;make room for an RGBColor and clear it
		CLR.W	-(SP)						;
Loop
		MOVE.L	(A4)+,D5					;pick up a 32-bit source pixel
		MOVE.B	D5,blue(SP)					;put blue byte in hi byte of blue component
		MOVE.B	D5,blue+1(SP)				;put blue byte in lo byte of blue component
		lsR.L	#8,D5						;get green in the lo byte
		MOVE.B	D5,green(SP)				;put green byte in hi byte of green component
		MOVE.B	D5,green+1(SP)				;put green byte in lo byte of green component
		lsR.L	#8,D5						;get red in the lo byte
		MOVE.B	D5,red(SP)					;put in red channel
		MOVE.B	D5,red+1(SP)				;put in red channel lo
		MOVE.L	stSProc(A6),stTmpProc(A6)	;make a copy of the search proc head
NxtProc
		MOVE.L	stTmpProc(A6),D0			;get sProcRec handle
		BEQ.S	OurTurn						;if not found using procs, use ITable
		MOVE.L	D0,A0						;move handle to address register
		MOVE.L	(A0),A0						;get sProcRec pointer
		MOVE.L	nxtSrch(A0),stTmpProc(A6)	;save handle to next sProcRec for later (might be NIL)

		CLR.B	-(SP)						;leave room for boolean result
		PEA		2(SP)						;push pointer to stack colorspec
		PEA		12(SP)						;push pointer to var result

		MOVE.L	srchProc(A0),A0				;get search proc address
		JSR		(A0)						;call search proc

		TST.B	(SP)+						;test result
		BEQ.S	NxtProc						;if FALSE, go to next searchProc

		MOVE.L	6(SP),D0					;get result in D0
		bra.s	writeItOut					;and put into output buffer

OurTurn										;go here if no search proc matched
		moveq	#0,d0
		move.b	red(sp),D0					;get red
		swap	d0
		move.b	green(sp),d0				;get green
		lsl.w	#8,d0
		move.b	blue(sp),d0					;get blue

writeItOut
		move.l	d0,(A3)+					;SAVE CURRENT LONG
		CMP.L	A2,A3						;DSTPTR >= DSTLIMIT?
		BLO.S	Loop						;if lower, continue to next pixel
DONESCL
		moveq	#1,d0						;force 32-bit mode							<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)

		ADDA.W	#10,SP						;release buffers
		MOVEM.L	(SP)+,A3-A5/D7				;RESTORE WORK REGISTERS
		RTS

		ENDPROC

;----------------------------------------------------
;
;	Perform a one time check to see if the search proc is the standard
;	SeedCFill or CalcCMask search procedure.  If it is then use an optimized
;	loop instead.

Search32toIndexed		PROC	EXPORT
						IMPORT	MySProc,MyCProc,SeedCFill32,CalcCMask32

		movem.l	a0-a2,-(sp)					;save work registers
		lea		Search32toInd,a0			;assume the hard case
		MOVE.L	stSProc(A6),a1				;get the search proc head
		MOVE.L	(a1),a1						;get sProcRec pointer
		MOVE.L	srchProc(a1),a1				;get search proc address
		lea		MySProc,a2					;point to seedCFill proc
		cmp.l	a1,a2						;are they the same?
		bne.s	@tryC
		lea		SeedCFill32,a0
		bra.s	@gotit

@tryC	lea		MyCProc,a2					;point to seedCFill proc
		cmp.l	a1,a2						;are they the same?
		bne.s	@gotIt
		lea		CalcCMask32,a0
@gotIt
		MOVE.L	A0,scaleCase(A6)			;remember to go there from now on
		move.l	a0,d0						;save scalecase in d0
		movem.l	(sp)+,a0-a2					;restore work registers
		jmp		(ZA0,d0.l)					;go there


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Search32toInd
;
; this routine converts a 32-bit direct pixel to a 1,2,4, or 8 bit destination
;	first applying the search proc for this device, then using a direct lookup
;	into the appropriate inverse table if that fails.  The stack frame is included
;	solely to copy the stack frame offsets from the caller in Stretch.
;

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;

		MOVEM.L	A3-A5/D6-D7,-(SP)			;SAVE WORK REGISTERS
		MOVE.L	A0,A4						;copy source buffer address to non-volatile register
		MOVE.L	A1,A3						;copy dest buffer address
		move.l	saveA5(a6),a5				;set up caller's A5 for the search proc		<1.5> BAL

		moveq	#0,d0						;force 24-bit mode							<1.5>
		move.l	a2,d7						;save a2 just for grins						<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.l	d7,a2						;restore a2 just in case					<1.5>

		MOVEQ	#0,D7						;init offset into destination
		CLR.L	-(SP)						;make room for SearchProc result
		CLR.L	-(SP)						;make room for an RGBColor and clear it
		CLR.W	-(SP)						;

NXTSLNG 
		MOVE.L	(A4)+,D5					;pick up a 32-bit source pixel
		MOVE.B	D5,blue(SP)					;put blue byte in hi byte of blue component
		MOVE.B	D5,blue+1(SP)				;put blue byte in lo byte of blue component
		ROR.L	#8,D5						;get green in the lo byte
		MOVE.B	D5,green(SP)				;put green byte in hi byte of green component
		MOVE.B	D5,green+1(SP)				;put green byte in lo byte of green component
		ROR.L	#8,D5						;get red in the lo byte
		MOVE.B	D5,red(SP)					;put in hi red channel
		MOVE.B	D5,red+1(SP)				;put in lo red channel
		MOVE.L	stSProc(A6),stTmpProc(A6)	;make a copy of the search proc head
NxtProc
		MOVE.L	stTmpProc(A6),D0			;get sProcRec handle
		BEQ.S	UseITable					;if not found using procs, use ITable
		MOVE.L	D0,A0						;move handle to address register
		MOVE.L	(A0),A0						;get sProcRec pointer
		MOVE.L	nxtSrch(A0),stTmpProc(A6)	;save handle to next sProcRec for later (might be NIL)

		CLR.B	-(SP)						;leave room for boolean result
		PEA		2(SP)						;push pointer to stack colorspec
		PEA		12(SP)						;push pointer to var result

		MOVE.L	srchProc(A0),A0				;get search proc address
		JSR		(A0)						;call search proc

		TST.B	(SP)+						;test result
		BEQ.S	NxtProc						;if FALSE, go to next searchProc

		MOVE.L	6(SP),D3					;get result in D3
		BRA.S	BuildLong					;and put into output buffer

UseITable									;go here if no search proc matched

		MOVE.L	stITabPtr(A6),A0			;get pointer to the inverse table (past header)
		MOVE.W	stITabRes(A6),D1			;get the iTable resolution
		move.b	red(sp),d5					;get red
		BFEXTU	D5{24:D1},D0				;extract iTabRes bits of red (clearing hi bits)
		LSL.L	D1,D0						;shift over by iTabRes

		move.b	green(sp),d5
		BFEXTU	D5{24:D1},D3				;get the green component
		OR.L	D3,D0						;put them together
		LSL.L	D1,D0						;shift again

		move.b	blue(sp),d5
		BFEXTU	D5{24:D1},D3					;get the blue component
		OR.L	D3,D0						;put them together to form iTable index

		MOVE.B	(A0,D0.L),D3				;get the index in D3 (hi 3 bytes still clear)

BuildLong
		BFINS	D3,D6{D7:D4}				;PUT TO DST LONG
		ADD		D4,D7						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D7						;TIME FOR NEXT DST LONG?
		BNE.S	NXTSLNG						;=>NO
		MOVE.L	D6,(A3)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A3						;DSTPTR >= DSTLIMIT?
		BLO.S	NXTSLNG						;if lower, continue to next pixel
DONESCL
		moveq	#1,d0						;force 32-bit mode							<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)

		ADDA.W	#10,SP						;release buffers
		MOVEM.L	(SP)+,A3-A5/D6-D7			;RESTORE WORK REGISTERS
		RTS

		ENDPROC	;Search32toIndexed


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

SeedCFill32		PROC	EXPORT
				Export	CalcCMask32
;
; this routine converts a 32-bit direct pixel to a 1 bit destination with zero's
; wherever the source matches the color pointed to by the GDRefcon field and
; one's everywhere else.
;

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


		moveq	#0,d1						;clear high bit of d1 to signal SeedCFill
		bra.s	share

CalcCMask32
		moveq	#-1,d1						;set high bit of d1 to signal CalcCMask

share
;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1- BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;

		move.l	a2,D5						;save end of dst buffer in D5
		MOVE.L	theGDevice,A2				;get handle to the gDevice
		MOVE.L	(A2),A2						;point to theGDevice
		MOVE.L	GDRefCon(A2),A2				;point to seed RGB
		move.l	(a2)+,d3					;get RRrrGGgg
		lsr.l	#8,d3						;get 00RRrrGG
		lsl.w	#8,d3						;get 00RRGG00
		move.b	(a2),d3						;get 00RRGGBB
		move.l	d5,a2						;restore end of dst buffer

		move.l	MaskBC,d0					;get low3bytes mask
		MOVEQ	#0,D4						;init offset into destination

NXTSLNG 
		MOVE.L	(A0)+,D5					;pick up a 32-bit source pixel
		and.l	d0,d5						;clear high byte for compare
		cmp.l	d5,d3						;compare to seed value
		sne.b	d1							;match ? d1=0 : d1=FF

BuildLong
		BFINS	D1,D2{D4:1}					;PUT TO DST LONG
		ADDq	#1,D4						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D4						;TIME FOR NEXT DST LONG?
		BNE.S	NXTSLNG						;=>NO

		addx.l	d1,d1						;tst high bit of d1
		subx.l	d1,d1						;extend high bit throughout long
		eor.l	d1,d2						;conditionally invert resulting bits

		MOVE.L	D2,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	NXTSLNG						;if lower, continue to next pixel
DONESCL

		RTS
		ENDPROC


Scale32to16	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 16 BIT DIRECT
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;  ASSUMES DST IS COMPOSED OF TWO BYTES OF THE FORM 'X:1  R:5  G:5  B:5'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;

		tst.b	-$a5(a6)
		bne.s	@different_implementation

		lea		@sexy_code,a4
		move.l	a4,-$228(a6)

@sexy_code
		move.l	a2,d2						;get ptr to end
		sub.l	a1,d2						;sub ptr to beginning
		lsr.l	#2,d2						;get long cnt in d1
		subq	#1,d2						;make zero based

		move.l	#$7fff7fff,d3

@NXTSLNG 
		MOVE.L	(A0)+,D0					;GET NEXT LONG OF SRC
		lsr.l	#3,d0
		lsl.b	#3,d0
		lsl		#3,d0
		lsr.l	#6,d0
		swap	d0

		MOVE.L	(A0)+,D1					;GET NEXT LONG OF SRC
		lsr.l	#3,d1
		lsl.b	#3,d1
		lsl		#3,d1
		lsr.l	#6,d1

		move.w	d1,d0
		and.l	d3,d0
		move.l	d0,(a1)+					;write out 2 pixels
		dbra	d2,@NXTSLNG					;loop for all longs in dst scanline
		RTS

@different_implementation
		clr.b	-$2a9(a6)
		lea		@sexy_code_2,a4
		move.l	a4,-$228(a6)

@sexy_code_2
		move.l	a2,d2
		sub.l	a1,d2
		lsr.l	#2,d2
		subq	#1,d2
		moveq.l	#3,d0
		and.b	-$2a9(a6),d0
		move.l	@data_tbl(d0.w*4),d3
		addq.b	#1,-$2a9(a6)

@loop
		moveq.l	#0,d1
		move.l	(a0)+,d0
		swap	d0
		add.b	d3,d0
		scs.b	d1
		or.b	d0,d1
		lsl.l	#5,d1
		swap	d0
		move.b	d0,d4
		lsr		#8,d0
		add.b	d3,d0
		scs.b	d1
		or.b	d0,d1
		lsl.l	#5,d1
		add.b	d3,d4
		scs.b	d1
		or.b	d4,d1
		lsr.l	#3,d1
		move	d1,d5
		rol.l	#8,d3
		swap	d5
		moveq.l	#0,d1
		move.l	(a0)+,d0
		swap	d0
		add.b	d3,d0
		scs.b	d1
		or.b	d0,d1
		lsl.l	#5,d1
		swap	d0
		move.b	d0,d4
		lsr		#8,d0
		add.b	d3,d0
		scs.b	d1
		or.b	d0,d1
		lsl.l	#5,d1
		add.b	d3,d4
		scs.b	d1
		or.b	d4,d1
		lsr.l	#3,d1
		move	d1,d5
		move.l	d5,(a1)+
		rol.l	#8,d3
		dbf		d2,@loop
		rts

@data_tbl
		dc.l	$05010400
		dc.l	$03070206
		dc.l	$04000501
		dc.l	$02060307


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Search32to16		PROC	EXPORT

;
; this routine converts a 32-bit direct pixel to a 16 bit destination
;	first applying the search proc for this device, then using a direct lookup
;	if that fails.  
;
;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 16 BIT DIRECT
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3-A5/D7,-(SP)				;SAVE WORK REGISTERS
		MOVE.L	A0,A4						;copy source buffer address to non-volatile register
		MOVE.L	A1,A3						;copy dest buffer address

		move.l	saveA5(a6),a5				;set up caller's A5 for the search proc		<1.5> BAL

		moveq	#0,d0						;force 24-bit mode							<1.5>
		move.l	a2,d7						;save a2 just for grins						<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.l	d7,a2						;restore a2 just in case					<1.5>

		CLR.L	-(SP)						;make room for SearchProc result
		CLR.L	-(SP)						;make room for an RGBColor and clear it
		CLR.W	-(SP)						;
		bra.s	loop

DoOne 
		MOVE.L	(A4)+,D5					;pick up a 32-bit source pixel
		MOVE.B	D5,blue+4(SP)				;put blue byte in hi byte of blue component
		MOVE.B	D5,blue+5(SP)				;put blue byte in lo byte of blue component
		ROR.L	#8,D5						;get green in the lo byte
		MOVE.B	D5,green+4(SP)				;put green byte in hi byte of green component
		MOVE.B	D5,green+5(SP)				;put green byte in lo byte of green component
		ROR.L	#8,D5						;get red in the lo byte
		MOVE.B	D5,red+4(SP)				;put in red channel hi
		MOVE.B	D5,red+5(SP)				;put in red channel lo
		MOVE.L	stSProc(A6),stTmpProc(A6)	;make a copy of the search proc head
NxtProc
		MOVE.L	stTmpProc(A6),D0			;get sProcRec handle
		BEQ.S	OurTurn						;if not found using procs, use ITable
		MOVE.L	D0,A0						;move handle to address register
		MOVE.L	(A0),A0						;get sProcRec pointer
		MOVE.L	nxtSrch(A0),stTmpProc(A6)	;save handle to next sProcRec for later (might be NIL)

		CLR.B	-(SP)						;leave room for boolean result
		PEA		2+4(SP)						;push pointer to stack colorspec
		PEA		12+4(SP)					;push pointer to var result

		MOVE.L	srchProc(A0),A0				;get search proc address
		JSR		(A0)						;call search proc

		TST.B	(SP)+						;test result
		BEQ.S	NxtProc						;if FALSE, go to next searchProc

		MOVE.L	6+4(SP),D0					;get result in D0
		rts									;and put into output buffer

OurTurn										;go here if no search proc matched
;
; take rgb from stack and convert to 5-5-5
;
		moveq	#0,d0
		move.b	red+4(sp),d0				;get high byte of red 	00000000rrrrrrrr
		lsl.w	#5,d0						;xxxrrrrrrrr00000
		move.b	green+4(sp),d0				;get high byte of green	xxxrrrrrgggggggg
		lsl.l	#5,d0						;0rr|rrrgggggggg00000
		move.b	blue+4(sp),d0				;0rr|rrrgggggbbbbbbbb
		lsr.l	#3,d0						;0rrrrrgggggbbbbb
		rts


Loop	bsr.s	DoOne						;process one input long
		move.w	d0,d7						;get low word
		swap	d7
		bsr.s	DoOne						;process one input long
		move.w	d0,d7						;get low word
		MOVE.L	D7,(A3)+					;SAVE CURRENT LONG
		CMP.L	A2,A3						;DSTPTR >= DSTLIMIT?
		BLO.S	Loop						;if lower, continue to next pixel
DONESCL
		moveq	#1,d0						;force 32-bit mode							<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)

		ADDA.W	#10,SP						;release buffers
		MOVEM.L	(SP)+,A3-A5/D7				;RESTORE WORK REGISTERS
		RTS
		ENDPROC


Scale16toIndexed	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF TWO BYTES OF THE FORM 'xrrrrrgg gggbbbbb'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;			A4:		PIXEL TRANSLATE TABLE
;
;	CLOBBERS A0-A1/D0-D5
;
		MOVEM.L	A3/A5/D6/D7,-(SP)			;SAVE WORK REGISTERS
		MOVEQ	#0,D2						;INIT OFFSET INTO DST

		MOVE.L	stITabPtr(A6),A3			;get pointer to the inverse table (past header)
		MOVE.W	stITabRes(A6),D1			;get the iTable resolution
		move.l	(a0)+,d5					;get first long of src
		bra.s	@first
@NXTSLNG 
		MOVE.L	(A0)+,D5					;GET NEXT LONG OF SRC
		cmp.l	d5,a5						;same as last long?
		beq.s	@again						;yes, go fast
@first
		move.l	d5,a5						;save last 32 bit pixel value

		BFEXTU	D5{1:D1},D0		;5,8,8		;extract iTabRes bits of red (clearing hi bits)
		LSL.L	D1,D0			;3,6,6		;shift over by iTabRes
		BFEXTU	D5{6:D1},D3		;5,8,8		;get the green component
		OR.L	D3,D0			;0,2,3		;put them together
		LSL.L	D1,D0			;3,6,6		;shift again
		BFEXTU	D5{11:D1},D3	;5,8,8		;get the blue component
		OR.L	D3,D0			;0,2,3		;put them together to form iTable index
								;21,40,42
		MOVE.B	(A3,D0.w),D0				;get the index in D0

		BFEXTU	D5{17:D1},D7	;5,8,8		;extract iTabRes bits of red (clearing hi bits)
		LSL.L	D1,D7			;3,6,6		;shift over by iTabRes
		BFEXTU	D5{22:D1},D3	;5,8,8		;get the green component
		OR.L	D3,D7			;0,2,3		;put them together
		LSL.L	D1,D7			;3,6,6		;shift again
		BFEXTU	D5{27:D1},D3	;5,8,8		;get the blue component
		OR.L	D3,D7			;0,2,3		;put them together to form iTable index
								;21,40,42
		MOVE.B	(A3,D7.w),D7				;get the index in D7

@again
		BFINS	D0,D6{D2:D4}				;PUT TO DST LONG
		ADD		D4,D2						;BUMP TO NEXT DST PIXEL
		BFINS	D7,D6{D2:D4}				;PUT TO DST LONG
		ADD		D4,D2						;BUMP TO NEXT DST PIXEL
		AND		#$1f,D2						;TIME FOR NEXT DST LONG?
		BNE.S	@NXTSLNG					;=>NO
		MOVE.L	D6,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	@NXTSLNG					;if lower, continue to next pixel
DONESCL
		MOVEM.L	(SP)+,A3/A5/D6/D7				;RESTORE WORK REGISTERS
		RTS



;----------------------------------------------------
;
;	Perform a one time check to see if the search proc is the standard
;	SeedCFill or CalcCMask search procedure.  If it is then use an optimized
;	loop instead.

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Search16toIndexed	PROC	EXPORT
						IMPORT	MySProc,MyCProc,SeedCFill16,CalcCMask16

		movem.l	a0-a2,-(sp)					;save work registers
		lea		Search16toInd,a0			;assume the hard case
		MOVE.L	stSProc(A6),a1				;get the search proc head
		MOVE.L	(a1),a1						;get sProcRec pointer
		MOVE.L	srchProc(a1),a1				;get search proc address
		lea		MySProc,a2					;point to seedCFill proc
		cmp.l	a1,a2						;are they the same?
		bne.s	@tryC
		lea		SeedCFill16,a0
		bra.s	@gotit

@tryC	lea		MyCProc,a2					;point to seedCFill proc
		cmp.l	a1,a2						;are they the same?
		bne.s	@gotIt
		lea		CalcCMask16,a0
@gotIt
		MOVE.L	A0,scaleCase(A6)			;remember to go there from now on
		move.l	a0,d0						;save scalecase in d0
		movem.l	(sp)+,a0-a2					;restore work registers
		jmp		(ZA0,d0.l)					;go there


Search16toInd

;
; this routine converts a 16-bit direct pixel to a 1,2,4, or 8 bit destination
;	first applying the search proc for this device, then using a direct lookup
;	into the appropriate inverse table if that fails.  The stack frame is included
;	solely to copy the stack frame offsets from the caller in Stretch.
;

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO 1-8 BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF TWO BYTES OF THE FORM 'xrrrrrgggggbbbbb'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;

		MOVEM.L	A3-A5/D6-D7,-(SP)			;SAVE WORK REGISTERS
		MOVE.L	A0,A4						;copy source buffer address to non-volatile register
		MOVE.L	A1,A3						;copy dest buffer address

		move.l	saveA5(a6),a5				;set up caller's A5 for the search proc		<1.5> BAL

		moveq	#0,d0						;force 24-bit mode							<1.5>
		move.l	a2,d7						;save a2 just for grins						<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.l	d7,a2						;restore a2 just in case					<1.5>

		MOVEQ	#0,D7						;init offset into destination
		CLR.L	-(SP)						;make room for SearchProc result
		CLR.L	-(SP)						;make room for an RGBColor and clear it
		CLR.W	-(SP)						;

NXTSLNG 
		MOVE.W	(A4)+,D5					;pick up a 16-bit source pixel
		lsl.l	#3,d5						;left align blue in lo byte
		move.b	d5,d0						;get 5 bits of blue
		lsl.l	#5,d0
		move.b	d5,d0						;10 bits of blue
		lsl.l	#5,d0
		move.b	d5,d0						;15 bits of blue
		lsl.l	#5,d0
		move.b	d5,d0						;blue up the wazoo
		lsr.l	#7,d0						;make a word of blue
		MOVE.w	D0,blue(SP)					;store out in color spec

		lsr.l	#5,d5						;left align green in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of green
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of green
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of green
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of green
		MOVE.w	D0,green(SP)				;store out in color spec

		lsr.l	#5,d5						;left align red in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of red
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of red
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of red
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of red
		MOVE.w	D0,red(SP)					;store out in color spec

		MOVE.L	stSProc(A6),stTmpProc(A6)	;make a copy of the search proc head
NxtProc
		MOVE.L	stTmpProc(A6),D0			;get sProcRec handle
		BEQ.S	OurTurn						;if not found using procs, use ITable
		MOVE.L	D0,A0						;move handle to address register
		MOVE.L	(A0),A0						;get sProcRec pointer
		MOVE.L	nxtSrch(A0),stTmpProc(A6)	;save handle to next sProcRec for later (might be NIL)

		CLR.B	-(SP)						;leave room for boolean result
		PEA		2(SP)						;push pointer to stack colorspec
		PEA		12(SP)						;push pointer to var result

		MOVE.L	srchProc(A0),A0				;get search proc address
		JSR		(A0)						;call search proc

		TST.B	(SP)+						;test result
		BEQ.S	NxtProc						;if FALSE, go to next searchProc

		MOVE.L	6(SP),D3					;get result in D3
		BRA.S	BuildLong					;and put into output buffer

OurTurn										;go here if no search proc matched

		MOVE.L	stITabPtr(A6),A0			;get pointer to the inverse table (past header)
		MOVE.W	stITabRes(A6),D1			;get the iTable resolution

		move.b	red(sp),d5
		BFEXTU	D5{24:D1},D0	;5,8,8		;extract iTabRes bits of red (clearing hi bits)
		LSL.L	D1,D0			;3,6,6		;shift over by iTabRes
		move.b	green(sp),d5
		BFEXTU	D5{24:D1},D3	;5,8,8		;get the green component
		OR.L	D3,D0			;0,2,3		;put them together
		LSL.L	D1,D0			;3,6,6		;shift again
		move.b	blue(sp),d5
		BFEXTU	D5{24:D1},D3	;5,8,8		;get the blue component
		OR.L	D3,D0			;0,2,3		;put them together to form iTable index
								;21,40,42
		MOVE.B	(A0,D0.w),D3				;get the index in D3 		<KON 12MAR90>

BuildLong
		BFINS	D3,D6{D7:D4}				;PUT TO DST LONG			<KON 12MAR90>
		ADD		D4,D7						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D7						;TIME FOR NEXT DST LONG?
		BNE.S	NXTSLNG						;=>NO
		MOVE.L	D6,(A3)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A3						;DSTPTR >= DSTLIMIT?
		BLO.S	NXTSLNG						;if lower, continue to next pixel
DONESCL
		moveq	#1,d0						;force 32-bit mode							<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)

		ADDA.W	#10,SP						;release buffers
		MOVEM.L	(SP)+,A3-A5/D6-D7			;RESTORE WORK REGISTERS
		RTS



; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

SeedCFill16		PROC	EXPORT
				Export	CalcCMask16
;
; this routine converts a 16-bit direct pixel to a 1 bit destination with zero's
; wherever the source matches the color pointed to by the GDRefcon field and
; one's everywhere else.
;

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


		moveq	#0,d1						;clear high bit of d1 to signal SeedCFill
		bra.s	share

CalcCMask16
		moveq	#-1,d1						;set high bit of d1 to signal CalcCMask

share
;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1- BIT INDEXED
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;

		move.l	a2,D5						;save end of dst buffer in D5
		MOVE.L	theGDevice,A2				;get handle to the gDevice
		MOVE.L	(A2),A2						;point to theGDevice
		MOVE.L	GDRefCon(A2),A2				;point to seed RGB
		move.w	(a2)+,d3					;get RRrr
		lsr.w	#1,d3						;clear high bit
		lsl.l	#6,d3						;save 6 bits in high word
		move.w	(a2)+,d3					;get GGrr
		lsl.l	#5,d3						;save 5 more bits in high word
		move.w	(a2),d3						;get BBbb
		lsr.l	#8,d3
		lsr.l	#3,d3						; convert to 5-5-5 pixel in low word
		move.l	d5,a2						;restore end of dst buffer

		moveq	#-1,d0						;get low 15 bits mask
		lsr.w	#1,d0
		MOVEQ	#0,D4						;init offset into destination

NXTSLNG 
		MOVE.w	(A0)+,D5					;pick up a 32-bit source pixel
		and.w	d0,d5						;clear high byte for compare
		cmp.w	d5,d3						;compare to seed value
		sne.b	d1							;match ? d1=0 : d1=FF

BuildLong
		BFINS	D1,D2{D4:1}					;PUT TO DST LONG
		ADDq	#1,D4						;BUMP TO NEXT DST PIXEL
		AND		#$1F,D4						;TIME FOR NEXT DST LONG?
		BNE.S	NXTSLNG						;=>NO

		addx.l	d1,d1						;tst high bit of d1
		subx.l	d1,d1						;extend high bit throughout long
		eor.l	d1,d2						;conditionally invert resulting bits

		MOVE.L	D2,(A1)+					;ELSE SAVE CURRENT LONG
		CMP.L	A2,A1						;DSTPTR >= DSTLIMIT?
		BLO.S	NXTSLNG						;if lower, continue to next pixel
DONESCL

		RTS
		ENDPROC



Scale16to32	PROC	EXPORT

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'

;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO 32 BIT DIRECT
;  ASSUMES DST IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;  ASSUMES SRC IS COMPOSED OF TWO BYTES OF THE FORM 'X:1  R:5  G:5  B:5'
;
;  USES:	A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;

		move.l	a2,d4						;get ptr to end
		sub.l	a1,d4						;sub ptr to beginning
		lsr.l	#3,d4						;get double long cnt in d4
		subq	#1,d4						;make zero based
		bmi.s	@do1More					;if only one, go do it			<BAL 26Apr89>
		MOVE.l	(A0)+,D5					;GET FIRST LONG OF SRC
		bra.s	@first

@NXTSLNG 
		MOVE.l	(A0)+,D5					;GET NEXT LONG OF SRC
		cmp.l	d0,d5						;same as last time?
		beq.s	@again						;yes, go fast
@first	move.l	d5,d0						;save this long of src

; Build second pixel in D3
@last
		moveq	#0,d3	;0,2,3				;start fresh
		move.w	d5,d1	;0,2,3				;make a copy
		lsr.w	#7,d1	;1,4,4				;left align red in low byte
		move.b	d1,d3	;0,2,3				;start with 5 bits of red
		lsl.l	#5,d3	;1,4,4				;save dstcmpsize (5) bits of red in high bytes
		move.b	d1,d3	;0,2,3				;get 3 bits of red
		lsl.l	#3,d3	;1,4,4				;save the 3 bits of red as well
		move.w	d5,d1	;0,2,3				;make a copy
		lsr.w	#2,d1	;1,4,4				;left align green in low byte
		move.b	d1,d3	;0,2,3				;start with 5 bits of green
		lsl.l	#5,d3	;1,4,4				;save dstcmpsize (5) bits of green in high bytes
		move.b	d1,d3	;0,2,3				;get 3 bits of green
		lsl.l	#3,d3	;1,4,4				;save the 3 bits of green as well
		move.b	d5,d1	;0,2,3				;make a copy
		lsl.b	#3,d1	;1,4,4				;left align blue in low byte
		move.b	d1,d3	;0,2,3				;start with 5 bits of blue
		lsl.l	#5,d3	;1,4,4				;save dstcmpsize (5) bits of blue in high bytes
		move.b	d1,d3	;0,2,3				;get 3 more bits of blue
		lsr.l	#5,d3	;1,4,4				;shift away extra blue bits

; Build first pixel in D2

		swap	d5							;get first pixel
		moveq	#0,d2	;0,2,3				;start fresh
		move.w	d5,d1	;0,2,3				;make a copy
		lsr.w	#7,d1	;1,4,4				;left align red in low byte
		move.b	d1,d2	;0,2,3				;start with 5 bits of red
		lsl.l	#5,d2	;1,4,4				;save dstcmpsize (5) bits of red in high bytes
		move.b	d1,d2	;0,2,3				;get 3 bits of red
		lsl.l	#3,d2	;1,4,4				;save the 3 bits of red as well
		move.w	d5,d1	;0,2,3				;make a copy
		lsr.w	#2,d1	;1,4,4				;left align green in low byte
		move.b	d1,d2	;0,2,3				;start with 5 bits of green
		lsl.l	#5,d2	;1,4,4				;save dstcmpsize (5) bits of green in high bytes
		move.b	d1,d2	;0,2,3				;get 3 bits of green
		lsl.l	#3,d2	;1,4,4				;save the 3 bits of green as well
		lsl.b	#3,d5	;1,4,4				;left align blue in low byte
		move.b	d5,d2	;0,2,3				;start with 5 bits of blue
		lsl.l	#5,d2	;1,4,4				;save dstcmpsize (5) bits of blue in high bytes
		move.b	d5,d2	;0,2,3				;get 3 more bits of blue
		lsr.l	#5,d2	;1,4,4				;shift away extra blue bits

@again	MOVE.L	D2,(A1)+					;SAVE FIRST PIXEL
		MOVE.L	D3,(A1)+					;SAVE SECOND PIXEL
		dbra	d4,@NXTSLNG					;loop for all longs in dst scanline
		cmp.l	a1,a2						;is there one more left?
		bne.s	@do1More					;yes go to it
		RTS
@do1More
	;	moveq	#0,d4						;only do one						<BAL 26Apr89>
	;	subq	#4,a1						;do last one again						"	"
	;	swap	d5							;put previous pixel first
		move.w	(a0)+,d5					;do this pixel last
	;	bra.s	@last

		moveq	#0,d2	;0,2,3				;start fresh
		move.w	d5,d1	;0,2,3				;make a copy
		lsr.w	#7,d1	;1,4,4				;left align red in low byte
		move.b	d1,d2	;0,2,3				;start with 5 bits of red
		lsl.l	#5,d2	;1,4,4				;save dstcmpsize (5) bits of red in high bytes
		move.b	d1,d2	;0,2,3				;get 3 bits of red
		lsl.l	#3,d2	;1,4,4				;save the 3 bits of red as well
		move.w	d5,d1	;0,2,3				;make a copy
		lsr.w	#2,d1	;1,4,4				;left align green in low byte
		move.b	d1,d2	;0,2,3				;start with 5 bits of green
		lsl.l	#5,d2	;1,4,4				;save dstcmpsize (5) bits of green in high bytes
		move.b	d1,d2	;0,2,3				;get 3 bits of green
		lsl.l	#3,d2	;1,4,4				;save the 3 bits of green as well
		lsl.b	#3,d5	;1,4,4				;left align blue in low byte
		move.b	d5,d2	;0,2,3				;start with 5 bits of blue
		lsl.l	#5,d2	;1,4,4				;save dstcmpsize (5) bits of blue in high bytes
		move.b	d5,d2	;0,2,3				;get 3 more bits of blue
		lsr.l	#5,d2	;1,4,4				;shift away extra blue bits				"	"
		MOVE.L	D2,(A1)						;write last pixel					<BAL 26Apr89>
		rts

; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Search16to32		PROC	EXPORT

;
; this routine converts a 16-bit direct pixel to a 32 bit destination
;	first applying the search proc for this device, then using a direct lookup
;	if that fails.  
;
;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO 32 BIT DIRECT
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;

		MOVEM.L	A3-A5/D7,-(SP)				;SAVE WORK REGISTERS
		MOVE.L	A0,A4						;copy source buffer address to non-volatile register
		MOVE.L	A1,A3						;copy dest buffer address

		move.l	saveA5(a6),a5				;set up caller's A5 for the search proc		<1.5> BAL

		moveq	#0,d0						;force 24-bit mode							<1.5>
		move.l	a2,d7						;save a2 just for grins						<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.l	d7,a2						;restore a2 just in case					<1.5>

		CLR.L	-(SP)						;make room for SearchProc result
		CLR.L	-(SP)						;make room for an RGBColor and clear it
		CLR.W	-(SP)						;

DoOne 
		MOVE.W	(A4)+,D5					;pick up a 16-bit source pixel
		lsl.l	#3,d5						;left align blue in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of blue
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of blue
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of blue
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of blue
		MOVE.w	D0,blue(SP)					;store out in color spec

		lsr.l	#5,d5						;left align green in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of green
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of green
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of green
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of green
		MOVE.w	D0,green(SP)				;store out in color spec

		lsr.l	#5,d5						;left align red in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of red
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of red
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of red
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of red
		MOVE.w	D0,red(SP)					;store out in color spec

		MOVE.L	stSProc(A6),stTmpProc(A6)	;make a copy of the search proc head
NxtProc
		MOVE.L	stTmpProc(A6),D0			;get sProcRec handle
		BEQ.S	OurTurn						;if not found using procs, use ITable
		MOVE.L	D0,A0						;move handle to address register
		MOVE.L	(A0),A0						;get sProcRec pointer
		MOVE.L	nxtSrch(A0),stTmpProc(A6)	;save handle to next sProcRec for later (might be NIL)

		CLR.B	-(SP)						;leave room for boolean result
		PEA		2(SP)						;push pointer to stack colorspec
		PEA		12(SP)						;push pointer to var result

		MOVE.L	srchProc(A0),A0				;get search proc address
		JSR		(A0)						;call search proc

		TST.B	(SP)+						;test result
		BEQ.S	NxtProc						;if FALSE, go to next searchProc

		MOVE.L	6(SP),D0					;get result in D0
		bra.s	Loop						;and put into output buffer

OurTurn										;go here if no search proc matched
;		moveq	#0,d0						;d0 is already 0
		move.b	red(sp),D0					;get red
		swap	d0
		move.b	green(sp),d0				;get green
		lsl.w	#8,d0
		move.b	blue(sp),d0					;get blue

Loop
		MOVE.L	D0,(A3)+					;SAVE CURRENT LONG
		CMP.L	A2,A3						;DSTPTR >= DSTLIMIT?
		BLO.S	DoOne						;if lower, continue to next pixel
DONESCL
		moveq	#1,d0						;force 32-bit mode							<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)

		ADDA.W	#10,SP						;release buffers
		MOVEM.L	(SP)+,A3-A5/D7				;RESTORE WORK REGISTERS
		RTS

		ENDPROC


; from QDciPatchROM.a verbatim												<sm 6/9/92>stb

Search16to16		PROC	EXPORT				;<20AUG90 KON>

;
; this routine converts a 16-bit direct pixel to a 16 bit destination
;	first applying the search proc for this device, then using a direct lookup
;	if that fails.  
;
;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'


;------------------------------------------------------------------
;
;  SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO 32 BIT DIRECT
;  ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
;  USES:	D3:		SRC PIXEL SIZE
;			D4:		DST PIXEL SIZE
;			A0:		SRC BUFFER
;			A1:		DST BUFFER
;			A2:		END OF DST BUFFER
;
;	CLOBBERS A0-A1/D0-D5
;

		MOVEM.L	A3-A5/D7,-(SP)				;SAVE WORK REGISTERS
		MOVE.L	A0,A4						;copy source buffer address to non-volatile register
		MOVE.L	A1,A3						;copy dest buffer address

		move.l	saveA5(a6),a5				;set up caller's A5 for the search proc		<1.5> BAL

		moveq	#0,d0						;force 24-bit mode							<1.5>
		move.l	a2,d7						;save a2 just for grins						<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
		move.l	d7,a2						;restore a2 just in case					<1.5>

		CLR.L	-(SP)						;make room for SearchProc result
		CLR.L	-(SP)						;make room for an RGBColor and clear it
		CLR.W	-(SP)						;
		bra		loop						;do 2 at a time								<20AUG90 KON>
DoOne 
		MOVE.W	(A4)+,D5					;pick up a 16-bit source pixel
		lsl.l	#3,d5						;left align blue in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of blue
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of blue
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of blue
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of blue
		MOVE.w	D0,blue+4(SP)				;store out in color spec

		lsr.l	#5,d5						;left align green in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of green
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of green
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of green
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of green
		MOVE.w	D0,green+4(SP)				;store out in color spec

		lsr.l	#5,d5						;left align red in lo byte
		move.b	d5,d0
		lsl.l	#5,d0						;get 5 bits of red
		move.b	d5,d0
		lsl.l	#5,d0						;make into 10 bits of red
		move.b	d5,d0
		lsl.l	#5,d0						;make into 15 bits of red
		move.b	d5,d0
		lsr.l	#7,d0						;get a word of red
		MOVE.w	D0,red+4(SP)				;store out in color spec

		MOVE.L	stSProc(A6),stTmpProc(A6)	;make a copy of the search proc head
NxtProc
		MOVE.L	stTmpProc(A6),D0			;get sProcRec handle
		BEQ.S	OurTurn						;if not found using procs, use ITable
		MOVE.L	D0,A0						;move handle to address register
		MOVE.L	(A0),A0						;get sProcRec pointer
		MOVE.L	nxtSrch(A0),stTmpProc(A6)	;save handle to next sProcRec for later (might be NIL)

		CLR.B	-(SP)						;leave room for boolean result
		PEA		2+4(SP)						;push pointer to stack colorspec
		PEA		12+4(SP)						;push pointer to var result

		MOVE.L	srchProc(A0),A0				;get search proc address
		JSR		(A0)						;call search proc

		TST.B	(SP)+						;test result
		BEQ.S	NxtProc						;if FALSE, go to next searchProc

		MOVE.L	6+4(SP),D3					;get result in D0
		rts									;and put into output buffer

OurTurn										;go here if no search proc matched
;
; take rgb from stack and convert to 5-5-5
;
		moveq	#0,d0
		move.b	red+4(sp),d0				;get high byte of red 	00000000rrrrrrrr
		lsl.w	#5,d0						;xxxrrrrrrrr00000
		move.b	green+4(sp),d0				;get high byte of green	xxxrrrrrgggggggg
		lsl.l	#5,d0						;0rr|rrrgggggggg00000
		move.b	blue+4(sp),d0				;0rr|rrrgggggbbbbbbbb
		lsr.l	#3,d0						;0rrrrrgggggbbbbb
		rts

Loop
		bsr.s	DoOne
		move.w	d0,d7
		swap	d7
		bsr.s	DoOne
		move.w	d0,d7
		MOVE.L	d7,(A3)+					;SAVE CURRENT LONG
		CMP.L	A2,A3						;DSTPTR >= DSTLIMIT?
		BLO.S	Loop						;if lower, continue to next pixel
DONESCL
		moveq	#1,d0						;force 32-bit mode							<1.5>
		_rSwapMMUMode						;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)

		ADDA.W	#10,SP						;release buffers
		MOVEM.L	(SP)+,A3-A5/D7				;RESTORE WORK REGISTERS
		RTS
		ENDPROC

			Include 'scaleBlt.a'





;******************************************************************************************
;******************************************************************************************
		if 0 then								;<14SEP90 SMC>
;******************************************************************************************
;******************************************************************************************

ANDY	PROC	EXPORT
				EXPORT	CB8to8Clip, CB8to1Clip, CB1to8Clip
				IMPORT	DoneStretch

;----------------------------------------------------
;
;  A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;  STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile	SETC	'STRETCH'

			INCLUDE	'DrawingVars.a'



; The world according to Andy:

;******************************************************************************************
;
; CB1To8Clip ($373) is the clipped copyBits loop used in the 1 to 8 expansion blits,
; common in programs like HyperCard and Servant.  If it's the typical case we can handle
; (black and white, source 1 bit,dest 8 bits), expand on the fly, right onto the screen,
; for a pretty big gain.

; it really shouldn't be named CB1to8, as it's the routine used for any scaling or lookup
; blit.  We also optimize the 8-bit to 8-bit blits that require table lookup, and also
; handle the 8 to 1 case



CB1To8Clip


;		MOVE.L	SRCROW(A6),D0
;		SUB.L	D0,SRCADDR(A6)		;back up one line


@NXTMSK1
		MOVE	VERT(A6),D0 				;GET CURRENT VERT COORD
		CMP 	MINRECT+TOP(A6),D0			;IS VERT < MINV ?
		BLT.S	@NODRAW						;YES, DON'T DRAW

		JSR 	([SEEKMASK,A6])				;MAKE MASK BUFFER CURRENT
		Bra.s	@GoForIt						;TAKE MODE JUMP
		MOVE.L	DSTROW(A6),D0				;GET DST ROWBYTES
		ADD.L	D0,DSTADDR(A6)				;BUMP DST TO NEXT ROW

@NODRAW	ADD 	#1,VERT(A6) 				;BUMP TO NEXT VERT
		MOVE	VERT(A6),D0 				;GET VERT
		CMP 	MINRECT+BOTTOM(A6),D0		;ARE WE AT THE LAST SCAN LINE ?
		BEQ		doneStretch					;YES, QUIT
		MOVE.L	SRCROW(A6),D2				;GET SRC ROWBYTES
		ADD.L	D2,SRCADDR(A6)				;BUMP SRC TO NEXT ROW
		BRA 	@NXTMSK1 					;ELSE continue to draw from this src			<BAL 19Mar89>


@GoForIt
		SUBQ	#1,BUFSIZE(A6)		;one less than they say
		MOVEQ	#0,d7				;inhibit zooming
		MOVE.L	DSTADDR(A6),A4				;INIT DSTPTR FOR ROW
		MOVE.L	RGNBUFFER(A6),A2			;INIT MASKPTR FOR ROW

; its our case, so handle it.  Pick up the shifted source with a bit-field instruction,
; then use it to plot 8 longwords, indirecting a nibble at a time through an expansion
; table.   Special case the edges, so we can really zoom if the middle's region is all ones.

; A2 has the region mask, A4 has the destination; use A3 to hold the source.
; D7 holds the "OK to zoom" (region all ones) flag

CB1to8Outer
		MOVE.L	DSTALIGN(A6),D0
		ASR.L	#3,D0

		MOVEQ	#15,D3			;D3 has 4 bit mask
		MOVEQ	#-1,D6			;D6 has -1 for region compare
		LEA		Table8,A1

		MOVE.L	SRCADDR(A6),A3		;get source pointer

		MOVE.L	SRCALIGN(A6),D5		;get shift count
		ADD.L	D0,D5

; OK, first do the left edge (one nybble worth)

		BFEXTU	(A3){D5:16},D4		;pick up next word of source
		ADDQ.L	#4,D5			;bump to next nibble
		ROL.W	#4,D4			;get next nibble

		MOVE.L	(A2)+,D1		;get region mask
		BEQ.S	@0										;<14SEP90 SMC>

		MOVE.W	D4,D0			;get low 4 bits
		AND.W	D3,D0
		MOVE.L	0(A1,D0.W*4),D0		;get source longword
		AND.L	D1,D0

		NOT.L	D1			;flip mask
		AND.L	(A4),D1
		OR.L	D1,D0			;combine source and dest
		MOVE.L	D0,(A4)	;+		;stuff it				;<14SEP90 SMC>
	@0:	ADDQ	#4,A4									;<14SEP90 SMC>

; OK, here's the loop that handles the middle, which is where all the action is

		MOVE.W	BUFSIZE(A6),D2		;get destination count

		CMP.W	#4,D2			;four or less we can't optimize
		BLE 	FinishLastFew

; if we have a multiple of 4 left to do, don't do last 4

		MOVE.W	D2,D0
		AND	#3,D0
		BNE.S	@1

		SUBQ	#1,D2
@1
		LSR	#2,D2			;do 4 longwords each iteration
		SUBQ	#1,D2

		TST.B	D7			;is region all ones?
		BNE	CB1to8SpLoop0		;if so, we can go super-fast

		ST	D7			;assume next like is special
CB1to8Loop
		BFEXTU	(A3){D5:16},D4		;pick up next word of source
		ADDQ	#2,A3			;bump it
		BEQ	CB1to8AllZeros		;special case all zeros
CB1to8AltEntry
		ROL.W	#4,D4			;get high nibble first

; OK, expand the low 4 bits in D4 into a longword, then plot it.  Fetch the region mask
; first, since it may not even be necessary

CB1to8Inner
		LEA	CB1to8Nib2,A5

		MOVE.L	(A2)+,D1		;get region mask

		MOVE.W	D4,D0			;get low 4 bits
		AND.W	D3,D0
		MOVE.L	0(A1,D0.W*4),D0		;get source longword

		CMP.L	D6,D1			;mask all ones?
		BNE 	CB1to8HardPlot		;if not, plot it the hard way

		MOVE.L	D0,(A4)+		;plot the longword

; now plot the 2nd nibble

CB1to8Nib2
		LEA	CB1to8Nib3,A5

		ROL.W	#4,D4			;get next nybble

		MOVE.L	(A2)+,D1		;get region mask

		MOVE.W	D4,D0			;get low 4 bits
		AND.W	D3,D0
		MOVE.L	0(A1,D0.W*4),D0		;get source longword

		CMP.L	D6,D1			;mask all ones?
		BNE.S  	CB1to8HardPlot	;if not, plot it the hard way

		MOVE.L	D0,(A4)+		;plot the longword

; now plot the 3rd nibble

CB1to8Nib3
		LEA	CB1to8Nib4,A5
		ROL.W	#4,D4			;get next nybble

		MOVE.L	(A2)+,D1		;get region mask

		MOVE.W	D4,D0			;get low 4 bits
		AND.W	D3,D0
		MOVE.L	0(A1,D0.W*4),D0	;get source longword

		CMP.L	D6,D1			;mask all ones?
		BNE.S	CB1to8HardPlot	;if not, plot it the hard way

		MOVE.L	D0,(A4)+		;plot the longword

; now plot the last nibble

CB1to8Nib4
		LEA	CB1to8NibBot,A5

		ROL.W	#4,D4			;get next nybble

		MOVE.L	(A2)+,D1		;get region mask

		MOVE.W	D4,D0			;get low 4 bits
		AND.W	D3,D0
		MOVE.L	0(A1,D0.W*4),D0		;get source longword

		CMP.L	D6,D1			;mask all ones?
		BNE.S 	CB1to8HardPlot		;if not, plot it the hard way

		MOVE.L	D0,(A4)+		;plot the longword
CB1to8NibBot
		DBRA	D2,CB1to8Loop		;loop until done

; clean up the last 0 to 3 nibbles; 4 remaining handled specially

FinishLastFew
		BFEXTU	(A3){D5:16},D4		;pick up last word of source
		LEA	BotFin1to8Loop,A5
		MOVE.W	BUFSIZE(A6),D2		;get the number left to do
		BEQ 	CB1to8NextLine		;if zero, we're done

		AND.W	#3,D2			;0 to 3 only
		BNE.S	BotFin1to8Loop

		MOVEQ	#3,D2			;4 to do
TopFin1to8Loop
		ROL.W	#4,D4

		MOVE.L	(A2)+,D1		;get region mask

		MOVE.W	D4,D0			;get low 4 bits
		AND.W	D3,D0
		MOVE.L	0(A1,D0.W*4),D0		;get source longword

		CMP.L	D6,D1			;mask all ones?
		BNE.S 	CB1to8HPNoInval		;if not, plot it the hard way (no edge)

		MOVE.L	D0,(A4)+		;plot the longword
BotFin1to8Loop
		DBRA	D2,TopFin1to8Loop
		BRA.S	CB1to8NextLine

; handle the case where the region mask is all zeros

CB1to8NoPlot
		ADDQ.L	#4,A4			;bump dest ptr
		JMP	(A5)			;advance to next one

; handle the more difficult case of a heterogenous region mask

CB1to8HardPlot
		MOVEQ	#0,D7			;not all ones
CB1to8HPNoInval
		TST.L	D1
		BEQ.S	CB1to8NoPlot

		AND.L	D1,D0

		NOT.L	D1			;flip mask
		AND.L	(A4),D1
		OR.L	D1,D0			;combine source and dest
		MOVE.L	D0,(A4)+		;stuff it
		JMP	(A5)

; to speed things up, we special case words of all zero and blast 4 long words of zero out as
; fast as we can, without having to do any lookups.

CB1to8AllZeros
		MOVE.L	(A2)+,D1		;get region mask
		BEQ.S	CBZEmpty1		;if all zeros, skip

		CMP.L	D6,D1			;all ones?
		BNE.S	CBZBIC1			;if not, skip

		CLR.L	(A4)+			;plot the zeros
CBZLong2
		MOVE.L	(A2)+,D1		;get region mask
		BEQ.S	CBZEmpty2		;if all zeros, skip

		CMP.L	D6,D1			;all ones?
		BNE.S	CBZBIC2			;if not, skip

		CLR.L	(A4)+			;plot the zeros
CBZLong3
		MOVE.L	(A2)+,D1		;get region mask
		BEQ.S	CBZEmpty3		;if all zeros, skip

		CMP.L	D6,D1			;all ones?
		BNE.S	CBZBIC3			;if not, skip

		CLR.L	(A4)+			;plot the zeros
CBZLong4
		MOVE.L	(A2)+,D1		;get region mask
		BEQ.S	CBZEmpty4		;if all zeros, skip

		CMP.L	D6,D1			;all ones?
		BNE.S	CBZBIC4			;if not, skip

		CLR.L	(A4)+			;plot the zeros
		BRA.S	CB1to8NibBot	;dive back in
CBZEmpty1
		MOVEQ	#0,D7
		ADDQ	#4,A4
		BRA.S	CBZLong2
CBZEmpty2
		MOVEQ	#0,D7
		ADDQ	#4,A4
		BRA.S	CBZLong3
CBZEmpty3
		MOVEQ	#0,D7
		ADDQ	#4,A4
		BRA.S	CBZLong4
CBZEmpty4
		MOVEQ	#0,D7
		ADDQ	#4,A4
		BRA	CB1to8NibBot
CBZBIC1
		MOVEQ	#0,D7
		NOT.L	D1
		AND.L	D1,(A4)+
		BRA.S	CBZLong2
CBZBIC2
		MOVEQ	#0,D7
		NOT.L	D1
		AND.L	D1,(A4)+
		BRA.S	CBZLong3
CBZBIC3
		MOVEQ	#0,D7
		NOT.L	D1
		AND.L	D1,(A4)+
		BRA.S	CBZLong4
CBZBIC4
		MOVEQ	#0,D7
		NOT.L	D1
		AND.L	D1,(A4)+
		BRA 	CB1to8NibBot


; all done with this line, so bump the pointers and loop until done 

CB1to8NextLine
		MOVE.L	DSTROW(A6),D0
		ADD.L	D0,DSTADDR(A6)		;bump to next line of destination

		MOVE.L	SRCROW(A6),D0
		ADD.L	D0,SRCADDR(A6)		;bump to next line of source

; bump line count and see if we're done

		MOVE.W	VERT(A6),D0
		ADDQ	#1,D0
		MOVE.W	D0,VERT(A6)

		CMP.W	MINRECT+BOTTOM(A6),D0		;all done?
		BEQ		DoneStretch				;if so, go Home

; create the region mask for the new scan line, and maintain the all one's flag

		CMP.W	STATEB+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB1to8NewRgn		;if so, go do it

		CMP.W	STATEB+THISV(A6),D0		;need to rebuild?
		BLT.S	CB1to8NewRgn		;if so, go do it

		CMP.W	STATEC+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB1to8NewRgn		;if so, go do it

		CMP.W	STATEC+THISV(A6),D0		;need to rebuild?
		BLT.S	CB1to8NewRgn		;if so, go do it

		CMP.W	STATEA+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB1to8NewRgn		;if so, go do it

		CMP.W	STATEA+THISV(A6),D0		;need to rebuild?
		BGE.S	Skip1to8Rgn		;if not, skip
CB1to8NewRgn
		MOVEQ	#0,D7			;invalidate region all ones flag

		MOVE.L	SEEKMASK(A6),A0
		JSR	(A0)			;make new region mask

; set up registers and go handle the next line

Skip1to8Rgn
		MOVE.L	RGNBUFFER(A6),A2
		MOVE.L	DSTADDR(A6),A4

		BRA	CB1to8Outer		;go process next line



; here's where we go when we've detected that region masking isn't necessary, so we can really
; blast things 4 longwords at a time

CB1to8SpLoop0
		MOVE.W	D2,D7			;remember the count

CB1to8SpLoop
		BFEXTU	(A3){D5:16},D4		;pick up next word of source
		ADDQ	#2,A3			;bump it
		BEQ.S	CB1to8SpAllZeros	;special case all zeros

		CMP.W	D4,D6			;all ones?
		BEQ.S	CB1to8SpAllOnes

		swap	d4				;keep src data in high word
		ROL.l	#4,D4			;get first nibble
		AND.W	D3,d4			;get low 4 bits
		MOVE.L	0(A1,D4.W*4),(A4)+	;plot expanded longword

		ROL.l	#4,D4			;get next nibble
		AND.W	D3,D4
		MOVE.L	0(A1,D4.W*4),(A4)+	;plot expanded longword

		ROL.l	#4,D4			;get next nibble
		AND.W	D3,D4
		MOVE.L	0(A1,D4.W*4),(A4)+	;plot expanded longword

		ROL.l	#4,D4			;get next nibble
		AND.W	D3,D4
		MOVE.L	0(A1,D4.W*4),(A4)+	;plot expanded longword

BotCB1to8SpLoop
		DBRA	D2,CB1to8SpLoop

; finish up the special case by adjusting A2 and diving back into common code

Finish1to8Sp
		ADDQ	#1,D7			;add one for real count
		LSL.W	#4,D7			;4 longs (16 bytes) per iteration
		ADD.W	D7,A2			;bump region pointer
		BRA	FinishLastFew		;finish the last few

; handle the case when the source word is all zero and there's no region clipping -- we
; can go as fast as we can.

CB1to8SpAllZeros
		CLR.L	(A4)+
		CLR.L	(A4)+
		CLR.L	(A4)+
		CLR.L	(A4)+

		BRA.S	BotCB1to8SpLoop

CB1to8SpAllOnes
		MOVE.L	D6,(A4)+
		MOVE.L	D6,(A4)+
		MOVE.L	D6,(A4)+
		MOVE.L	D6,(A4)+

		BRA.S	BotCB1to8SpLoop


;******************************************************************************************

CB8to81st0
		ADDQ	#4,A3			;bump source ptr
		ADDQ	#4,A4			;bump dest ptr
		BRA 	CB8to8Middle


; Handler for the 8 to 8 copyBits case (with mapping).  The basic strategy is the usual
; region counting, with the added twist of a single element cache for the longword mapping,
; using A1 to hold the pre-map and D7 to hold the post-mapped values.

CB8to8Clip
	;	MOVE.L	SRCROW(A6),D0
	;	SUB.L	D0,SRCADDR(A6)		;back up one line


@NXTMSK1
		MOVE	VERT(A6),D0 				;GET CURRENT VERT COORD
		CMP 	MINRECT+TOP(A6),D0			;IS VERT < MINV ?
		BLT.S	@NODRAW						;YES, DON'T DRAW

		JSR 	([SEEKMASK,A6])				;MAKE MASK BUFFER CURRENT
		Bra.s	@GoForIt						;TAKE MODE JUMP
		MOVE.L	DSTROW(A6),D0				;GET DST ROWBYTES
		ADD.L	D0,DSTADDR(A6)				;BUMP DST TO NEXT ROW

@NODRAW	ADD 	#1,VERT(A6) 				;BUMP TO NEXT VERT
		MOVE	VERT(A6),D0 				;GET VERT
		CMP 	MINRECT+BOTTOM(A6),D0		;ARE WE AT THE LAST SCAN LINE ?
		BEQ		doneStretch					;YES, QUIT
		MOVE.L	SRCROW(A6),D2				;GET SRC ROWBYTES
		ADD.L	D2,SRCADDR(A6)				;BUMP SRC TO NEXT ROW
		BRA 	@NXTMSK1 					;ELSE continue to draw from this src			<BAL 19Mar89>


@GoForIt
		SUBQ	#1,BUFSIZE(A6)		;one less than they say
		MOVEQ	#-1,D6				;D6 has -1 for region compare

		MOVEQ	#0,D4
		MOVEQ	#0,D3				;init region counting regs

		MOVE.L	SCALETBL(A6),A5		;get mapping table
		SUB.L	A1,A1				;use zero for initial input cache	<BAL 30Apr89>
		MOVE.L	(A5),D0				;compute output cache value			<BAL 30Apr89>
		MOVE.B	D0,D7				;map 1st byte						<BAL 30Apr89>
		LSL.L	#8,D7				;									<BAL 30Apr89>
		MOVE.B	D0,D7				;map 2nd byte						<BAL 30Apr89>
		MOVE.W	D7,D0				;get 2 mapped bytes					<BAL 30Apr89>
		SWAP	D7					;									<BAL 30Apr89>
		MOVE.W	D0,D7				;map 3rd and 4th bytes				<BAL 30Apr89>

CB8to8Outer
		MOVE.L	RGNBUFFER(A6),A2
		MOVE.L	SRCADDR(A6),A3		;get source pointer
		MOVE.L	DSTADDR(A6),A4		;get destptr
		MOVE.L	SCALETBL(A6),A5		;get mapping table

; offset source pointer according to bit offsets

		MOVE.L	DSTALIGN(A6),D0		;get shift count
		ASR.L	#3,D0
		MOVE.L	SRCALIGN(A6),D1
		ASR.L	#3,D1
		ADD.L	D1,D0
		ADD.L	D0,A3				;offset source ptr

; OK, first do the left edge

		MOVE.W	BUFSIZE(A6),D2		;get the count

		MOVEQ	#0,D5

		MOVE.L	(A2)+,D1			;get region mask
		BEQ.S	CB8to81st0			;if zero, handle it

; fetch the 1st source longword and map it through the table pointed to by A5

		MOVE.L	(A3)+,D0			;get source longword
		MOVE.L	D0,A1				;remember it

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 1st byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 2nd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 3rd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 4th byte
		ROL.L	#8,D0

		MOVE.L	D0,D7			;remember result of mapping

; plot it using the region mask

		AND.L	D1,D0
		NOT.L	D1			;flip mask
		AND.L	(A4),D1
		OR.L	D1,D0			;combine source and dest
		MOVE.L	D0,(A4)+		;stuff it

		SUBQ	#1,D2
		BMI.S	CB8to8NextLine

; if the region runs in D4 are still valid, we can use special code to really plot super
; fast.

CB8to8Middle
		TST.W	D4			;is it valid?
		BNE	V8to8PlotRgnRuns	;if so, go super fast

		MOVEQ	#-1,D4			;validate it for next time
		MOVEQ	#0,D3			;zero the run count

; see what the next region longword is.  Go to three different loops depending on whether
; the region is all ones, zeros or both

		MOVE.L	(A2)+,D1		;fetch next word of region mask
		BEQ 	V8to8FirstZero0		;if zero, go handle

		CMP.L	D6,D1			;all one's?
		BNE	V8to8StartSecondRun	;if not, skip

		BRA.S	V8to8FirstOnes1

; here's the loop that counts and plots the first run of all ones

V8to8FirstOnes
		MOVE.L	(A2)+,D1

		CMP.L	D6,D1			;is it still all ones?
		BNE 	V8to8StartSecondRun	;if not, end the run
V8to8FirstOnes1
		ADDQ.W	#1,D3			;bump the run count

		MOVE.L	(A3)+,D0		;fetch from source
		CMP.L	D0,A1			;same as before?
		BNE.S	@0

		MOVE.L	D7,D0
		BRA.S	@1
@0
		MOVE.L	D0,A1

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 1st byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 2nd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 3rd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 4th byte
		ROL.L	#8,D0
		MOVE.L	D0,D7
@1
		MOVE.L	D0,(A4)+		;store at destination

		DBRA	D2,V8to8FirstOnes	;loop until we're done

; OK, all done with this line, so bump the pointers and loop until done

CB8to8NextLine
		MOVE.L	DSTROW(A6),D0
		ADD.L	D0,DSTADDR(A6)		;bump to next line of destination

		MOVE.L	SRCROW(A6),D0
		ADD.L	D0,SRCADDR(A6)		;bump to next line of source

; bump line count and see if we're done

		MOVE.W	VERT(A6),D0
		ADDQ	#1,D0
		MOVE.W	D0,VERT(A6)

		CMP.W	MINRECT+BOTTOM(A6),D0		;all done?
		BEQ 	DoneStretch				;if so, use common exit

; create the region mask for the new scan line, and maintain the all ones flag

		CMP.W	STATEB+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB8to8NewRgn		;if so, go do it

		CMP.W	STATEB+THISV(A6),D0		;need to rebuild?
		BLT.S	CB8to8NewRgn		;if so, go do it

		CMP.W	STATEC+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB8to8NewRgn		;if so, go do it

		CMP.W	STATEC+THISV(A6),D0		;need to rebuild?
		BLT.S	CB8to8NewRgn		;if so, go do it

		CMP.W	STATEA+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB8to8NewRgn		;if so, go do it

		CMP.W	STATEA+THISV(A6),D0		;need to rebuild?
		BGE 	CB8to8Outer		;if not, skip
CB8to8NewRgn
		MOVEQ	#0,D4			;invalidate region all ones flag

		MOVE.L	A1,-(SP)
		MOVE.L	SEEKMASK(A6),A0
		JSR	(A0)			;make new region mask
		MOVE.L	(SP)+,A1

; go handle the next line

		BRA	CB8to8Outer		;go process next line

Fin8to8Zeros
		ADDQ	#4,A4
		BRA.S	CB8to8NextLine

; here's the loop that counts and plots the first run of all zeros

V8to8FirstZero
		MOVE.L	(A2)+,D1
		BNE.S	V8to8StartSecondRun
V8to8FirstZero0
		SUBQ.W	#1,D3			;decrement run count for zeros

		ADDQ	#4,A3
		ADDQ	#4,A4
		DBRA	D2,V8to8FirstZero

		BRA.S	CB8to8NextLine

; the region mask is heterogenous, so plot the word and start the second run.

V8to8StartSecondRun
		SWAP	D3

		MOVE.L	(A3)+,D0		;fetch from source
		CMP.L	D0,A1			;same as before?
		BNE.S	@0

		MOVE.L	D7,D0
		BRA.S	@1
@0
		MOVE.L	D0,A1
		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 1st byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 2nd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 3rd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 4th byte
		ROL.L	#8,D0
		MOVE.L	D0,D7
@1
		AND.L	D1,D0			;mask it
		NOT.L	D1			;flip mask
		AND.L	(A4),D1			;combine with source
		OR.L	D1,D0			;form dest longword
		MOVE.L	D0,(A4)+		;deposit it

		SUBQ	#1,D2
		BMI.S	Done8to8SecondRun

; sample the region and case out for the 2nd time

		MOVE.L	(A2)+,D1		;fetch next word of region mask
		BEQ.S	V8to8Zero0		;if zero, go handle

		CMP.L	D6,D1			;all one's?
		BNE.S	V8to8StartLastRun	;if not, skip

		BRA.S	V8to8Ones1

; here's the loop that counts and plots the second run of all ones

V8to8Ones
		MOVE.L	(A2)+,D1

		CMP.L	D6,D1			;is it still all ones?
		BNE.S	V8to8StartLastRun	;if not, end the run
V8to8Ones1
		ADDQ.W	#1,D3			;bump the run count

		MOVE.L	(A3)+,D0		;fetch from source
		CMP.L	D0,A1			;same as before?
		BNE.S	@0

		MOVE.L	D7,D0
		BRA.S	@1
@0
		MOVE.L	D0,A1
		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 1st byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 2nd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 3rd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 4th byte
		ROL.L	#8,D0
		MOVE.L	D0,D7
@1
		MOVE.L	D0,(A4)+		;store at destination

		DBRA	D2,V8to8Ones		;loop until we're done
Done8to8SecondRun
		SWAP	D3
		BRA	CB8to8NextLine		;all done

; here's the loop that counts the 2nd run of zeros

V8to8Zero
		MOVE.L	(A2)+,D1
		BNE.S	V8to8StartLastRun
V8to8Zero0
		SUBQ.W	#1,D3

		ADDQ	#4,A3
		ADDQ	#4,A4			;bump dest reg

		DBRA	D2,V8to8Zero		;loop until it changes

		BRA.S	Done8to8SecondRun

; OK, we've accumulated two runs, so finish up the line without counting

V8to8StartLastRun
		SWAP	D3

		TST.L	D1
		BEQ.S	V8to8LastZero
		BRA.S	V8to8LastLoopA
V8to8LastLoop
		MOVE.L	(A2)+,D1		;get region
		BEQ.S	V8to8LastZero
V8to8LastLoopA
		CMP.L	D6,D1
		BNE.S	V8to8LastHard

		MOVE.L	(A3)+,D0		;fetch from source
		CMP.L	D0,A1			;same as before?
		BNE.S	@0

		MOVE.L	D7,D0
		BRA.S	@1
@0
		MOVE.L	D0,A1
		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 1st byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 2nd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 3rd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 4th byte
		ROL.L	#8,D0
		MOVE.L	D0,D7
@1
		MOVE.L	D0,(A4)+		;store at destination
		DBRA	D2,V8to8LastLoop

		BRA	CB8to8NextLine
V8to8LastZero
		ADDQ	#4,A4
		ADDQ	#4,A3
		DBRA	D2,V8to8LastLoop
		BRA	CB8to8NextLine
V8to8LastHard
		MOVE.L	(A3)+,D0		;fetch from source
		CMP.L	D0,A1			;same as before?
		BNE.S	@0

		MOVE.L	D7,D0
		BRA.S	@1
@0
		MOVE.L	D0,A1
		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 1st byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 2nd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 3rd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 4th byte
		ROL.L	#8,D0
		MOVE.L	D0,D7
@1
		AND.L	D1,D0			;mask it
		NOT.L	D1			;flip mask
		AND.L	(A4),D1			;combine with source
		OR.L	D1,D0			;form dest longword
		MOVE.L	D0,(A4)+		;deposit it

		DBRA	D2,V8to8LastLoop
		BRA	CB8to8NextLine

; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D3.

V8to8PlotRgnRuns
		TST.W	D3			;which type of run?
		BPL.S	V8to8BlastPat1		;if ones, go blast it
		BEQ 	V8to8PlotRHard1		;if zero, plot one slowly, then plot 2nd run

; it's negative, so just skip over 4 times the count

		MOVE.W	D3,D0

		NEG.W	D0			;turn into longword count
		LSL.W	#2,D0			;times 4

		ADD.W	D0,A2			;skip over region
		ADD.W	D0,A3			;skip over source
		ADD.W	D0,A4			;skip over destination

		ADD.W	D3,D2			;decrement count
		BMI	CB8to8NextLine		;if done, skip

; now handle the second run

V8to8PRRun2
		LEA	@0,A0			;plot the break longword
		BRA 	V8to8PlotHardCommon
@0
		MOVE.L	D3,D0			;which type of run?
 		BPL.S	V8to8BlastPat2		;if ones, go blast it
		BEQ.S 	V8to8PlotRHard2

; it's negative, so we can skip over like above

		SWAP	D0
		NEG.W	D0			;turn into longword count
		SUB.W	D0,D2			;decrement count

		LSL.W	#2,D0			;times 4

		ADD.W	D0,A2			;skip over region
		ADD.W	D0,A3			;skip over source
		ADD.W	D0,A4			;skip over destination

		TST.W	D2
		BMI	CB8to8NextLine		;if done, skip

; we've interpreted both runs, so finish up using common code

		BRA	V8to8LastLoop

; Handle blasting out the first run

V8to8BlastPat1
		MOVE.W	D3,D0			;get the size

		MOVE.W	D0,D1
		LSL	#2,D1			;times 4
		ADD.W	D1,A2			;bump region ptr
		SUB.W	D0,D2

		LEA	V8to8PRRun2,A0
		BRA.S	V8to8BlastPatBot

; Blast out the second run

V8to8BlastPat2
		SWAP	D0			;use high word for 2nd run

		MOVE.W	D0,D1
		LSL	#2,D1			;times 4
		ADD.W	D1,A2			;bump region ptr
		SUB.W	D0,D2

		LEA	V8to8LastLoop,A0
		BRA.S	V8to8BlastPatBot
V8to8BlastPat
		MOVE.L	(A3)+,D1		;fetch from source
		CMP.L	D1,A1			;same as before?
		beq.s	@1

		MOVE.L	D1,A1
		MOVE.B	D1,D5
		MOVE.B	3(A5,D5.W*4),D1		;map 1st byte
		ROL.L	#8,D1

		MOVE.B	D1,D5
		MOVE.B	3(A5,D5.W*4),D1		;map 2nd byte
		ROL.L	#8,D1

		MOVE.B	D1,D5
		MOVE.B	3(A5,D5.W*4),D1		;map 3rd byte
		ROL.L	#8,D1

		MOVE.B	D1,D5
		MOVE.B	3(A5,D5.W*4),D1		;map 4th byte
		ROL.L	#8,D1
		MOVE.L	D1,D7
@1
		MOVE.L	d7,(A4)+		;store at destination
V8to8BlastPatBot
		DBRA	D0,V8to8BlastPat

; all done with plotting run of ones

		TST.W	D2
		BMI	CB8to8NextLine

		JMP	(A0)

; handle the heterogenous plots between runs

V8to8PlotRHard1
		LEA	V8to8PRRun2,A0
		BRA.S	V8to8PlotHardCommon
V8to8PlotRHard2
		LEA	V8to8LastLoop,A0
V8to8PlotHardCommon
		MOVE.L	(A2)+,D1		;get region mask

		MOVE.L	(A3)+,D0		;fetch from source
		CMP.L	D0,A1			;same as before?
		BNE.S	@0

		MOVE.L	D7,D0
		BRA.S	@1
@0
		MOVE.L	D0,A1
		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 1st byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 2nd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 3rd byte
		ROL.L	#8,D0

		MOVE.B	D0,D5
		MOVE.B	3(A5,D5.W*4),D0		;map 4th byte
		ROL.L	#8,D0
		MOVE.L	D0,D7
@1
		AND.L	D1,D0			;mask it
		NOT.L	D1			;flip mask
		AND.L	(A4),D1			;combine with source
		OR.L	D1,D0			;form dest longword
		MOVE.L	D0,(A4)+		;deposit it

		SUBQ	#1,D2			;count it
		BMI	CB8to8NextLine

		JMP	(A0)



;******************************************************************************************


; Handler for the 8 to 1 copyBits case (mapped ).  The basic strategy is the usual
; region counting, with the added twist of a single element cache for the longword mapping,
; using A1 to hold the pre-map and D7 to hold the post-mapped values.


CB8to11st0
		ADD.W	#32,A3			;bump source ptr
		ADDQ	#4,A4			;bump dest ptr
		BRA.S 	CB8to1Middle


CB8to1Clip
	;	MOVE.L	SRCROW(A6),D0
	;	SUB.L	D0,SRCADDR(A6)		;back up one line


@NXTMSK1
		MOVE	VERT(A6),D0 				;GET CURRENT VERT COORD
		CMP 	MINRECT+TOP(A6),D0			;IS VERT < MINV ?
		BLT.S	@NODRAW						;YES, DON'T DRAW

		JSR 	([SEEKMASK,A6])				;MAKE MASK BUFFER CURRENT
		Bra.s	@GoForIt						;TAKE MODE JUMP
		MOVE.L	DSTROW(A6),D0				;GET DST ROWBYTES
		ADD.L	D0,DSTADDR(A6)				;BUMP DST TO NEXT ROW

@NODRAW	ADD 	#1,VERT(A6) 				;BUMP TO NEXT VERT
		MOVE	VERT(A6),D0 				;GET VERT
		CMP 	MINRECT+BOTTOM(A6),D0		;ARE WE AT THE LAST SCAN LINE ?
		BEQ		doneStretch					;YES, QUIT
		MOVE.L	SRCROW(A6),D2				;GET SRC ROWBYTES
		ADD.L	D2,SRCADDR(A6)				;BUMP SRC TO NEXT ROW
		BRA 	@NXTMSK1 					;ELSE continue to draw from this src			<BAL 19Mar89>


@GoForIt
		SUBQ	#1,BUFSIZE(A6)		;one less than they say
		MOVEQ	#-1,D6			;D6 has -1 for region compare

		MOVEQ	#0,D4
		MOVEQ	#0,D3			;init region counting regs

		SUB.L	A1,A1
		SUBQ.L	#1,A1			;all ones for initial
		MOVEQ	#-1,D7			;map cache values
CB8to1Outer
		MOVE.L	RGNBUFFER(A6),A2
		MOVE.L	SRCADDR(A6),A3		;get source pointer
		MOVE.L	DSTADDR(A6),A4		;get destptr
		MOVE.L	SCALETBL(A6),A5		;get mapping table

; offset source pointer according to bit offsets

		MOVE.L	DSTALIGN(A6),D0		;get shift count
		MOVE.L	SRCALIGN(A6),D1
		ASR.L	#3,D1
		ADD.L	D1,D0
		ADD.L	D0,A3			;offset source ptr

; OK, first do the left edge

		MOVE.W	BUFSIZE(A6),D2		;get the count

		MOVEQ	#0,D5

		MOVE.L	(A2)+,D1		;get region mask
		BEQ.S	CB8to11st0		;if zero, handle it

; fetch the 1st source longword and map it through the table pointed to by A5

		BSR	Map8to1

; plot it using the region mask

		AND.L	D1,D0
		NOT.L	D1			;flip mask
		AND.L	(A4),D1
		OR.L	D1,D0			;combine source and dest
		MOVE.L	D0,(A4)+		;stuff it

		SUBQ	#1,D2
		BMI.S	CB8to1NextLine

; if the region runs in D4 are still valid, we can use special code to really plot super
; fast.

CB8to1Middle
		TST.W	D4			;is it valid?
		BNE	V8to1PlotRgnRuns	;if so, go super fast

		MOVEQ	#-1,D4			;validate it for next time
		MOVEQ	#0,D3			;zero the run count

; see what the next region longword is.  Go to three different loops depending on whether
; the region is all ones, zeros or both

		MOVE.L	(A2)+,D1		;fetch next word of region mask
		BEQ.S 	V8to1FirstZero0		;if zero, go handle

		CMP.L	D6,D1			;all one's?
		BNE	V8to1StartSecondRun	;if not, skip

		BRA.S	V8to1FirstOnes1

; here's the loop that counts and plots the first run of all ones

V8to1FirstOnes
		MOVE.L	(A2)+,D1

		CMP.L	D6,D1			;is it still all ones?
		BNE.S 	V8to1StartSecondRun	;if not, end the run
V8to1FirstOnes1
		ADDQ.W	#1,D3			;bump the run count

		BSR	Map8to1
		MOVE.L	D0,(A4)+		;store at destination

		DBRA	D2,V8to1FirstOnes	;loop until we're done

; OK, all done with this line, so bump the pointers and loop until done

CB8to1NextLine
		MOVE.L	DSTROW(A6),D0
		ADD.L	D0,DSTADDR(A6)		;bump to next line of destination

		MOVE.L	SRCROW(A6),D0
		ADD.L	D0,SRCADDR(A6)		;bump to next line of source

; bump line count and see if we're done

		MOVE.W	VERT(A6),D0
		ADDQ	#1,D0
		MOVE.W	D0,VERT(A6)

		CMP.W	MINRECT+BOTTOM(A6),D0	;all done?
		BEQ 	DoneStretch		;if so, use common exit

; create the region mask for the new scan line, and maintain the all ones flag

		CMP.W	STATEB+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB8to1NewRgn		;if so, go do it

		CMP.W	STATEB+THISV(A6),D0		;need to rebuild?
		BLT.S	CB8to1NewRgn		;if so, go do it

		CMP.W	STATEC+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB8to1NewRgn		;if so, go do it

		CMP.W	STATEC+THISV(A6),D0		;need to rebuild?
		BLT.S	CB8to1NewRgn		;if so, go do it

		CMP.W	STATEA+NEXTV(A6),D0		;rebuild the region?
		BGE.S	CB8to1NewRgn		;if so, go do it

		CMP.W	STATEA+THISV(A6),D0		;need to rebuild?
		BGE 	CB8to1Outer		;if so, go do it
CB8to1NewRgn
		MOVEQ	#0,D4			;invalidate region all ones flag

		MOVE.L	A1,-(SP)
		MOVE.L	SEEKMASK(A6),A0
		JSR	(A0)			;make new region mask
		MOVE.L	(SP)+,A1

; go handle the next line

		BRA	CB8to1Outer		;go process next line

Fin8to1Zeros
		ADDQ	#4,A4
		BRA.S	CB8to1NextLine

; here's the loop that counts and plots the first run of all zeros

V8to1FirstZero
		MOVE.L	(A2)+,D1
		BNE.S	V8to1StartSecondRun
V8to1FirstZero0
		SUBQ.W	#1,D3			;decrement run count for zeros

		ADD.W	#32,A3
		ADDQ	#4,A4
		DBRA	D2,V8to1FirstZero

		BRA.S	CB8to1NextLine

; the region mask is heterogenous, so plot the word and start the second run.

V8to1StartSecondRun
		SWAP	D3

		BSR	Map8to1

		AND.L	D1,D0			;mask it
		NOT.L	D1			;flip mask
		AND.L	(A4),D1			;combine with source
		OR.L	D1,D0			;form dest longword
		MOVE.L	D0,(A4)+		;deposit it

		SUBQ	#1,D2
		BMI.S	Done8to1SecondRun

; sample the region and case out for the 2nd time

		MOVE.L	(A2)+,D1		;fetch next word of region mask
		BEQ.S	V8to1Zero0		;if zero, go handle

		CMP.L	D6,D1			;all one's?
		BNE.S	V8to1StartLastRun	;if not, skip

		BRA.S	V8to1Ones1

; here's the loop that counts and plots the second run of all ones

V8to1Ones
		MOVE.L	(A2)+,D1

		CMP.L	D6,D1			;is it still all ones?
		BNE.S	V8to1StartLastRun	;if not, end the run
V8to1Ones1
		ADDQ.W	#1,D3			;bump the run count
		BSR	Map8to1			;fetch and map it
		MOVE.L	D0,(A4)+		;store at destination

		DBRA	D2,V8to1Ones		;loop until we're done
Done8to1SecondRun
		SWAP	D3
		BRA	CB8to1NextLine		;all done

; here's the loop that counts the 2nd run of zeros

V8to1Zero
		MOVE.L	(A2)+,D1
		BNE.S	V8to1StartLastRun
V8to1Zero0
		SUBQ.W	#1,D3

		ADD.W	#32,A3
		ADDQ	#4,A4			;bump dest reg

		DBRA	D2,V8to1Zero		;loop until it changes

		BRA.S	Done8to1SecondRun

; OK, we've accumulated two runs, so finish up the line without counting

V8to1StartLastRun
		SWAP	D3

		TST.L	D1
		BEQ.S	V8to1LastZero
		BRA.S	V8to1LastLoopA
V8to1LastLoop
		MOVE.L	(A2)+,D1		;get region
		BEQ.S	V8to1LastZero
V8to1LastLoopA
		CMP.L	D6,D1
		BNE.S	V8to1LastHard

		BSR	Map8to1

		MOVE.L	D0,(A4)+		;store at destination
		DBRA	D2,V8to1LastLoop

		BRA	CB8to1NextLine
V8to1LastZero
		ADDQ	#4,A4
		ADD.W	#32,A3
		DBRA	D2,V8to1LastLoop
		BRA	CB8to1NextLine
V8to1LastHard
		BSR	Map8to1

		AND.L	D1,D0			;mask it
		NOT.L	D1			;flip mask
		AND.L	(A4),D1			;combine with source
		OR.L	D1,D0			;form dest longword
		MOVE.L	D0,(A4)+		;deposit it

		DBRA	D2,V8to1LastLoop
		BRA	CB8to1NextLine

; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D3.

V8to1PlotRgnRuns
		TST.W	D3			;which type of run?
		BPL.S	V8to1BlastPat1		;if ones, go blast it
		BEQ.S 	V8to1PlotRHard1		;if zero, plot one slowly, then plot 2nd run

; it's negative, so just skip over 4 times the count

		MOVE.W	D3,D0

		NEG.W	D0			;turn into longword count
		LSL.W	#2,D0			;times 4

		ADD.W	D0,A2			;skip over region
		ADD.W	D0,A4			;skip over destination
		LSL	#3,D0			;times 8 for source
		ADD.W	D0,A3			;skip over source

		ADD.W	D3,D2			;decrement count
		BMI	CB8to1NextLine		;if done, skip

; now handle the second run

V8to1PRRun2
		LEA	@0,A0			;plot the break longword
		BRA.S	V8to1PlotHardCommon
@0
		MOVE.L	D3,D0			;which type of run?
 		BPL.S	V8to1BlastPat2		;if ones, go blast it
		BEQ.S 	V8to1PlotRHard2

; it's negative, so we can skip over like above

		SWAP	D0
		NEG.W	D0			;turn into longword count
		SUB.W	D0,D2			;decrement count

		LSL.W	#2,D0			;times 4

		ADD.W	D0,A2			;skip over region
		ADD.W	D0,A4			;skip over destination
		LSL	#3,D0			;times 8 for source
		ADD.W	D0,A3			;skip over source

		TST.W	D2
		BMI	CB8to1NextLine		;if done, skip

; we've interpreted both runs, so finish up using common code

		BRA.S	V8to1LastLoop

; Handle blasting out the first run

V8to1BlastPat1
		MOVE.W	D3,D0			;get the size

		MOVE.W	D0,D1
		LSL	#2,D1			;times 4
		ADD.W	D1,A2			;bump region ptr
		SUB.W	D0,D2

		MOVE.W	D0,D1
		LEA	V8to1PRRun2,A0
		BRA.S	V8to1BlastPatBot

; Blast out the second run

V8to1BlastPat2
		SWAP	D0			;use high word for 2nd run

		MOVE.W	D0,D1
		LSL	#2,D1			;times 4
		ADD.W	D1,A2			;bump region ptr
		SUB.W	D0,D2

		MOVE.W	D0,D1
		LEA	V8to1LastLoop,A0
		BRA.S	V8to1BlastPatBot
V8to1BlastPat
		BSR.S	Map8to1
		MOVE.L	D0,(A4)+		;store at destination
V8to1BlastPatBot
		DBRA	D1,V8to1BlastPat

; all done with plotting run of ones

		TST.W	D2
		BMI	CB8to1NextLine

		JMP	(A0)

; handle the heterogenous plots between runs

V8to1PlotRHard1
		LEA	V8to1PRRun2,A0
		BRA.S	V8to1PlotHardCommon
V8to1PlotRHard2
		LEA	V8to1LastLoop,A0
V8to1PlotHardCommon
		MOVE.L	(A2)+,D1		;get region mask

		BSR.S	Map8to1

		AND.L	D1,D0			;mask it
		NOT.L	D1			;flip mask
		AND.L	(A4),D1			;combine with source
		OR.L	D1,D0			;form dest longword
		MOVE.L	D0,(A4)+		;deposit it

		SUBQ	#1,D2			;count it
		BMI	CB8to1NextLine

		JMP	(A0)

; Map8to1 is the routine that takes 8 longwords from the source (pointed to by A3)
; and returns the single longword result in D0.  

Map8to1
	;	MOVEQ	#0,D0			;start dest at 0
		MOVE.L	(A5),D0			;check mapping for color 0		<BAL 04Apr89>
		BEQ.s	@a				;if white->white, ok			<dÃb> 12Jul88
		MOVEQ	#$F,D0			;else, its black				<dÃb> 12Jul88
@a								;								<dÃb> 12Jul88

		MOVEQ	#7,D7			;8 longs to process
		SUB.L	A1,A1			;set last source to 0
Map8to1Loop
		MOVE.L	(A3)+,D6		;fetch from source
		CMP.L	A1,D6			;same as last time?
		BEQ.S	Map8to1Fast		;if so, we've got the

		MOVE.L	D6,A1			;remember for next time

		swap	d6				;get next pixel
		MOVE.B	D6,D5			;get current pixel
		lsr.w	#8,d6
		MOVE.B	3(A5,D6.W*4),D6	;get mapped bit
		LSR.W	#1,D6			;get bit into carry
		ADDX.L	D0,D0			;shift it in 		optimized 04Jul89 GGD

		MOVE.B	3(A5,D5.W*4),D5		;get mapped bit
		LSR.W	#1,D5			;get bit into carry
		ADDX.L	D0,D0			;shift it in 		optimized 04Jul89 GGD

		swap	d6				;get next pixel
		MOVE.B	D6,D5			;get current pixel
		lsr.w	#8,d6
		MOVE.B	3(A5,D6.W*4),D6	;get mapped bit
		LSR.W	#1,D6			;get bit into carry
		ADDX.L	D0,D0			;shift it in 		optimized 04Jul89 GGD

		MOVE.B	3(A5,D5.W*4),D5		;get mapped bit
		LSR.W	#1,D5			;get bit into carry
		ADDX.L	D0,D0			;shift it in 		optimized 04Jul89 GGD

		DBRA	D7,Map8to1Loop

		MOVEQ	#-1,D6			;restore comparison mask
		RTS

; handle the case where it was the same as the last one, so we can repeat the
; high 4 bits

Map8to1Fast
		MOVEQ	#$0f,D5			; 					optimized 04Jul89 GGD
		AND.B	D0,D5			; 					optimized 04Jul89 GGD
		LSL.L	#4,D0
		OR.B	D5,D0

		DBRA	D7,Map8to1Loop

		MOVEQ	#-1,D6
		RTS

		ENDPROC 

;******************************************************************************************
;******************************************************************************************
		ENDIF								;<14SEP90 SMC>
;******************************************************************************************
;******************************************************************************************