sys7.1-doc-wip/QuickDraw/Stretch.a
2019-07-27 22:37:48 +08:00

11960 lines
362 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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 doesnt get built for
; CubeE. (Itll 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, dont 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 longs 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 doesnt 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
;
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
@NXTSLNG
MOVE.L (A0)+,D0 ;GET NEXT LONG OF SRC
ror.l #8,d0
lsr.w #3,d0
ror.l #5,d0
lsr.w #3,d0
ror.l #6,d0 ;16 bit pixel in high word
MOVE.L (A0)+,D1 ;GET NEXT LONG OF SRC
ror.l #8,d1
lsr.w #3,d1
ror.l #5,d1
lsr.w #3,d1
ror.l #6,d1 ;16 bit pixel in high word
swap d1 ;merge pixels
move.w d1,d0
move.l d0,(a1)+ ;write out 2 pixels
dbra d2,@NXTSLNG ;loop for all longs in dst scanline
RTS
; 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>
;******************************************************************************************
;******************************************************************************************