; ; File: Stretch.a ; ; Copyright: © 1981-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32 ; so they can coditionalized out of the build. ; 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. ; 6/11/92 stb stb Synch with QDciPatchROM.a; added comments to ; StretchBits, MapModeTable, SRCONE, stNoStack, stMask0, ; stMASK0Slow, stHilite, arith. transfer loops for 16 & 32 ; bits/pixel, OneColor, DoubleColor, QUADColor, EightLoop, ; BWtoD15Alpha, BWtoD24Alpha, AverageH16, Dither32toIndexed, ; Dither16toIndexed, Dither32toGray, Dither16toGray, ; Dither16toBitmap, Search32to32, Search32toInd, SeedCFill32, ; Search32to16, Search16toIndexed, SeedCFill16, Search16to32, ; Search16to16. ; <63> 5/5/92 SAH Put fix for clipped vertical stretch back in for Cube-E ; <62> 1/15/92 KC Fix "Short branch to the next instruction changed to a NOP" ; assembler warning. ; <61> 10/4/91 JSM Change PsychoticFarmerOrLater conditionals to TheFuture. ; <60> 10/2/91 DTY Conditionalise last changes for TheFuture. ; <59> 10/2/91 KON Fix bug where CopyBits was crashing when vertically stretching a ; pixmap that is clipped at the top. ; <58> 10/2/91 KON Save and restore stklowPt (rather than just setting it to sp on ; exit) in stretch. This fixes a bug where someone turns off the ; stack sniffer and then calls stretch which turns it back on. ; Also, abort picture playback when QDError = AbortPicPlayBackErr. ; <57> 10/2/91 KON Save and restore stklowPt (rather than just setting it to sp on ; exit) in stretch. This fixes a bug where someone turns off the ; stack sniffer and then calls stretch which turns it back on. ; Abort picture playback when QDError = AbortPicPlayBackErr. ; <56> 9/13/91 DTY Conditionalise previous change so it doesn’t get built for ; CubeE. (It’ll get built for PsychoticFarmerAndLater.) Move in ; code that was taken out between <54> and <55>, and build it for ; CubeE only. ; <55> 7/23/91 KON Speed up indexed to 32-bit srcCopy mode. Speed up colorized ; text: don't take scale case when depths are the same. ; <54> 3/19/91 KON DTY, WRKSHT#SAH-QD-055: Some pixmaps created with an old version ; of ResEdit had the high bit of pmVersion set. This causes the ; pmVersion macro to crash, so I removed it. ; <53> 3/18/91 KON GSC and JT: WKSHT# SAH-QD-054 16-bit source shrinks crash ; because the average buffer is calculated from the promoted ; depth, rather than the real depth. ; <52> 3/6/91 KON CEL: BRC# 84369 Register D0 was getting trashed when search ; procs were attached to direct destinations. Also, color ; calculation for 16-bits was incorrect when search proc is ; installed. ; <51> 2/19/91 KON DDG: WorkSheet #KS-003, MaskAddr in stackframe is not ; initialized if there is not a mask. This was causing crashes in ; some cases since verticle merge scanline routines look at the ; maskaddr. ; <50> 1/25/91 KON DDG: BRC# 81625, A fix in QDciPatchROM.a required reorganizing ; part of stretch. This change keeps the files in synchronization. ; <49> 1/23/91 KON Optimize and clean up code that was rushed for B4. [SMC] ; <48> 1/14/91 KON Fix PixMaps with nil color tables and CopyDeepMask with 1-bit ; mask. Fix bug in pmVersion macro. [SMC] ; <47> 1/11/91 KON Register was getting trashed around call to SeekMask. This ; caused CopyBits with more 3 regions to get trashed as in the ; KeyCaps CDEV. [DDG] ; <46> 12/17/90 KON Fix one of the problems with NIL color tables. [smc] ; <45> 11/26/90 SMC Fixed pattern hilite once and for all, and forced arithmetic ; transfers to direct devices into rgnblt instead of the slower ; loops in bitblt. With BAL. ; <44> 11/12/90 KON Fix problem with colorizing when dithering from an indexed src ; to an indexed destination. [smc] ; <43> 11/9/90 KON Copy rectangles to local stack and fixed problems with negative ; pmVersions. ; <42> 10/31/90 SMC Fixed alpha channel bugs with BAL. ; <41> 9/25/90 KON If source is 1-bit black and white and we are not shrinking, ; clear dither bit. (With SMC). ; <40> 9/18/90 SMC Fix transparent, addMax, subOver, and addMin transfers with a ; pattern. ; <39> 9/18/90 BG Removed <25>. 040s are behaving more reliably now. ; <38> 9/14/90 SMC Commented out all of the QuickerDraw routines and changed the ; logic to send those cases through ScaleBlt which are now faster ; and smaller (by about 1K). This implicitly fixes a bus error ; problem under AU/X when scaling from a 1-bit screen to the left ; edge of an 8-bit screen. ; <37> 9/13/90 KON NEEDED FOR BETA: Fix problem where promoting source to RGB is ; messed up. This showed up when the source is 1-bit. Also fixed ; in QDciPatchROM.a. ; <36> 9/10/90 KON Fixed one-bit to one-bit colorized copy. ; <35> 9/6/90 KON Fix 16 to indexed search loop. ; <34> 9/5/90 KON Fix copymask from an indexed src. The pmtable was not set ; correctly. ; <33> 9/4/90 KON fix problem where ctseed for 1-bit sources was getting trashed. ; If direct destination and search proc installed, use versions of ; fg and bg colors which have not been changed by the proc to do ; colorizing. ; <32> 8/26/90 KON Fix Search16to32 and Search32to16 stack frame referencing. Add ; 32-bit clean versions of MaskPixPmTable and SrcPixPmTable to ; stack frame. ; <31> 8/21/90 KON Always call search proc if one exists. If search proc fails, ; still use search procs RGBColor. Replicate bits when passing ; 16-bit source color to search procs. ; <30> 8/15/90 KON Fixed transparent mode which was writing outside the destination ; rectangle. Turned off colorizing for arithmetic modes. ; <29> 7/23/90 KON Fix CopyMask in cases where left and right edge are displaying ; garbage. ; <28> 7/20/90 gbm Change some identifiers to avoid assembly conflicts ; <27> 7/17/90 KON Fix 16-bit source notCopy mode. ; <26> 7/10/90 KON Fixed CopyMask for 16-bit sources, and cases where 16-bit masks ; were failing. Also fixed vertical shrinking of 1-bit sources. ; <26> 7/9/90 KON Fixed CopyMask for 16-bit sources, and cases where16-bit masks ; were failing. ; <25> 6/28/90 BG Added EclipseNOPs for flakey 040s. ; <24> 6/5/90 KON Speed up notCopy mode for direct src to direct dst by using ; invert flag. ; <23> 6/4/90 KON Speed things that slowed down up by checking if colorizing is a ; nop. ; <22> 5/29/90 HJR Fix Mac32 build problem by moving table8 and some code saving ; mods. ; <21> 5/24/90 KON Fix transfer modes for direct devices, and fix colorizing for ; indexed devices. ; <19+> 4/12/90 KON Add deep masks for copymask. ; <19> 4/11/90 KON Suppress colorizing in src blits when the src clut is nil (i.e. ; the colors are a ramp between the foreground and background ; colors. ; <18> 3/13/90 KON Part of file got trashed. Now fixed. ; <17> 3/13/90 KON Fixed bug in 16-bit search proc. ; <16> 3/6/90 KON Fixed error term for vertical shrinking so expanding and then ; shrinking by an integral amount does not alter the image. ; <15> 2/23/90 KON Fixed buffer problem in Dither16toGray. ; <14> 2/23/90 KON Fixed Dither32toGray and Dither16toGray. Random dots were ; displayed because error term was not calculated right. ; <13> 2/23/90 KON Added 16-bit shrink. ; <12> 2/16/90 KON Cleared out high end of register of ErrBuf size calculation. ; <11> 2/14/90 KON Try to get 256K in stNoStack. Memory requirement calculation now ; use longs so high bits aren't lost. StackFree is updated ; correctly. ; <10> 2/14/90 BAL Changed MFTemp memory stack allocation to try for upto 128K ; chunk. ; <9> 2/9/90 BAL Fixed dither 8-bit to 32-bit stretched copybits. ; <8> 2/5/90 BAL Fixed bug in vertical shrinking while performing indexed to ; indexed dither. ; <7> 2/1/90 BAL Dither16toIndexed: Fix dither error calculation for 16 bit ; sources being displayed on color indexed devices. ; <6> 2/1/90 BAL Special cased SeedCFill/CalcCMask search procs for 16 and 32 bit ; sources. ; <5> 1/30/90 BAL Fixed bugs in underflow of error when dithering to a grayscale ; or bitmap destination. This affects Dither32toGray/Bitmap and ; Dither16toGray/Bitmap. ; <4> 1/28/90 KON Fix clipping when destination is clipped at the top. ; <3> 1/28/90 BAL Added the depth conversion routines Dither32toBitmap and ; Dither16toBitmap and changed the decision tree to utilize them. ; <1+> 1/3/90 BAL FOR 6.0.5: Submitted latest version to BBS. Changes include ; indexed to indexed dithering support. ; <1.9> 12/9/89 BAL Fixed bug in accumulation of dither error in some of the loops. ; Should fix in others. Fixed a bug and optimized the case of ; source rects with tops above srcbits.bounds. ; <1.8> 9/25/89 BAL Changed "NOT forROM" conditionals to "useColorICON" and ; defaulted it to false ; <1.7> 7/16/89 GGD GGD for the vacationing BAL, Fixed bug in AverageH when ; averaging 2 pixels, and optimized the entire loop at the same ; time. ; <•1.6> 7/14/89 BAL For Aurora: Final CQD ; <1.5> 6/30/89 BAL Make A5 valid and return to 24 bit mode before calling search ; procs ; <•1.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final ; 5/26/89 BAL Fixed bug in call to MakeITable if seed mismatch during direct ; to indexed copy. ; <•1.3> 4/12/89 BAL Blasting in 32-Bit QuickDraw 1.0B1 ; 9/26/88 BAL Replace successfully TrimRect'ed rgns with wideopen to avoid ; multiple Trims. ; 9/22/88 BAL Moved initialization of region state records into GetSeek. ; 9/19/88 BAL Altered to use common stack frame file 'Drawing Vars.a' ; 9/18/88 BAL Altered to get CRSRFLAG value from _BitsToPix; Removed ; references to PIXSRC; ; 9/4/88 BAL Added area averaging for shrinking of 32 bit pixmaps. ; 8/29/88 BAL Changed 32 to 8-1bit dither to carry 2-D error. ; 6/28/88 BAL Added special scaling routine for B/W 1 bit to direct RGB in a ; 32 bit pixel. ; 6/27/88 BAL Changed pattern expansion routines for 16 and 32 bits to ; optimize for solid. ; 6/17/88 BAL Added routines to depth scale from direct to indexed devices. ; 5/9/88 BAL Altered depth scaling code to use long sized pixel translation ; table. ; 5/4/88 BAL fixed bug in n*8x scaling (n=3,5,6,7...) ; 5/3/88 BAL fixed 2 scaling bugs where word-sized operations overflowed ; 4/9/88 BAL altered to use 32bit addressing during blit to screens ; 12/7/87 BAL Changed to restore D7 (invertFlag) before returning to ; rgn/bitBlt. ; 11/8/87 BAL Forced stretch to only do color table pixel translation if ; absolutely necessary. ; 11/8/87 BAL Forced stretch to TrimRect(clipRgn,MinRect) before submitting to ; rgnBlt. ; 11/8/87 BAL Fixed computation of bufSize for more accurate region clipping ; at at depths greater than 1. ; 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. ; 08Nov87 BAL Forced stretch to TrimRect(clipRgn,MinRect) before submitting to rgnBlt. ; 08Nov87 BAL Fixed computation of bufSize for more accurate region clipping at ; at depths greater than 1. ; 07Dec87 BAL Changed to restore D7 (invertFlag) before returning to rgn/bitBlt. ; 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 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 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. ; ; 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 ;---------------------------------------------------- ; ; 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) 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 _GetBackColor ;get bg color for colorizing _GetForeColor move.w XLateFlag(a6),d0 ;restore translation flags 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 move.b RGBFrColor+4(a6),d1 ;blue rrrrrgggggbbbbbbbb lsr.l #3,d1 ; 000rrrrrgggggbbbbb 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 ; move.b RGBBgColor+4(a6),d1 ;blue lsr.l #3,d1 ; 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 BTST #5,D2 ; the ivert flag and skip bit 2 clear BNE.S @notnot ; 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 ; 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? 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 beq XScaleBLT ;nil table so must remap colors move.l d2,a0 ;get handle for deref 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. 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 ? BEQ.S @chkClip ;=>yes, go check clipRgn MOVE.L RGNB(A6),-(SP) ;PUSH visRgn HANDLE 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 MOVE.L GRAFGLOBALS(A1),A1 ;point to QD globals MOVE.L WIDEOPEN(A1),RGNB(A6) ;replace visRgn with wideOpen @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 PEA MINRECT(A6) ;PUSH ADDR OF MINRECT MOVE.W #-1,-(SP) ;pass Trim = True _TRIMRECT ;CALL TRIMRECT 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 MOVE.L RGNC(A6),RGNA(A6) ;replace clipRgn with userRgn MOVE.L A1,RGNC(A6) ;replace userRgn with clipRgn BRA XRGNBLT ;=>USE RGNBLT 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 _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) ; 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 ; _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? blt.s @noAvrg ;yes, skip averaging @shrink sge useAverage(a6) ;always average if 16 or 32bit src 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 add.l d1,d2 ;d2 is byte cnt/2 of AvrgBuf ; ; 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? cmp.w #4,realSrcShift(a6) ;source 16-bit data (check real source)? beq.s @DoWords ;Twice as many pixels, allocate twice the error buffer 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 @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 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 ; @noErr MOVE.L ([theGDevice]),A2 ; redereference in case it moved 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 ; 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 move.l d0,d1 ;make a copy ADD.l D0,D0 ;6 bytes (R.w,G.w,B.w) per pixel add.l d1,d0 ;d0 is byte cnt/2 of ErrBuf @gray LSR.l #1,D0 ;AND DIV BY 2 FOR LONGS 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 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 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 beq.s DOXLATE ;table not nil so continue move.l d0,a0 ;get handle for deref move.l (a0),a0 ;point to it 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. ; ; 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) 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 ; 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 ;------------------------------------------------------------------------------------------ ; ; 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 MOVE.L SP,ScaleTbl(A6) ;SAVE TRANSLATION TABLE just in case ;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 <> BRA NOTSTR ;jump back and decide between bitblt and rgnblt ;don't really have to use stretch at all! ;------------------------------------------------------------------------------------------ ; ; 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. ; 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 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 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 ext.l d1 ;clear out high word lsl.l d4,d1 ;convert to bits subq.l #1,d1 ;force downward round LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 addq.l #1,d1 ;***make it one based for stretch!! BTST #5,locMode+1(A6) ;arithmetic? BNE.S @skipDotToLong ;if so, don’t update bufSize MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 @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 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. tst d5 ; and #7,d5 ;alignment required? bra.s @mustAlign clr.l SRCALIGN(A6) ;remember to skip alignment pass clr.l dstBufBump(A6) ;init to no bump clr.l scaleBufBump(A6) ;init to no bump move.l SRCBUF(A6),d1 ;REMEMBER WHERE SRCBUF was move.l srcRow(a6),d2 sub.l d2,d0 ;anticipate initial bump move.l d0,srcBuf(a6) ;use srcAddr as srcBuf cmp.l DSTBUF(A6),d1 ;is dstBuf same as srcBuf? bne.s @mustAlign move.l d0,dstBuf(a6) ;use srcAddr as dstBuf move.l d2,dstBufBump(a6) ;set up rowBump for dstBuf cmp.l SCALEBUF(A6),d1 ;is scaleBuf same as srcBuf? bne.s @mustAlign move.l d0,scaleBuf(a6) ;use srcAddr as scaleBuf move.l d2,scaleBufBump(a6) ;set up rowBump for scaleBuf 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 ** <> beq.s @skipColor ;if so, skip colorizing. 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 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) ; 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 tst.b useDither(a6) ; are we dithering? bne.s dstOK ; yes dither this scan again with current error BRA NXTMSK1 ;ELSE continue to draw from this src ;----------------------------------------------------------------- ; ; 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 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 ; move.l d0,stackFree(a6) ; 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 ; swap d0 ;try for 256K _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 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 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 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 ; 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 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 stb stMASK0Slow ;------------------------------------------------------- ; ; MODE 0 OR 4: SRC --> DST ; ; FOR PROPER INVERSION, ASSUME SRC IS COLORED. INVERT SRC AFTER ; ADDING COLOR TO IT (RATHER THAN EXCHANGING FG AND BK, INVERT THEM). ; BFEXTU (A3){D6:0},D0 ;get an aligned long from bitmap ADD #4,A3 ;bump to next long of source MOVE.L (A2)+,D1 ;GET MASK EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET MOVE.L D0,D5 ;COPY SRC AND.L D3,D0 ;ADD FG COLOR TO SRC NOT.L D5 ;GET NOT SRC AND.L D4,D5 ;ADD BK COLOR TO NOT SRC OR.L D5,D0 ;COMBINE FG/BK DATA AND.L D1,D0 ;MASK RESULT NOT.L D1 ;FORM NOTMASK AND.L (A4),D1 ;GET DST DATA OR.L D1,D0 ;MERGE WITH SRC DATA MOVE.L D0,(A4)+ ;PUT RESULT IN DST DBRA D2,stMASK0Slow ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;GO FOR NEXT ROW endif ALIGN Alignment ;------------------------------------------------------- ; ; MODE 1 OR 5: SRC OR DST --> DST ; ; ASSUME SRC IS EXPANDED BLACK/WHITE PATTERN. SRC IS USED ; TO PUNCH DST, FG APPLIED TO SRC, THEN COMBINED WITH DST. ; stMASK1 BFEXTU (A3){D6:0},D0 ;get an aligned long from bitmap ADD #4,A3 ;bump to next long of source EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET MOVE.L (A2)+,D1 ;GET MASK AND.L D1,D0 ;MASK SRC MOVE.L D0,D1 ;COPY MASKED SRC AND.L D3,D1 ;ADD FG COLOR TO SRC NOT.L D0 ;GET NOT MASKED SRC AND.L (A4),D0 ;USE TO PUNCH OUT DST OR.L D1,D0 ;COMBINE SRC AND DST MOVE.L D0,(A4)+ ;PUT RESULT TO DST DBRA D2,stMASK1 ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment ;------------------------------------------------------- ; ; MODE 2 OR 6: SRC XOR DST --> DST ; stMASK2 BFEXTU (A3){D6:0},D0 ;get an aligned long from bitmap ADD #4,A3 ;bump to next long of source EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L (A2)+,D0 ;AND WITH MASK EOR.L D0,(A4)+ ;XOR RESULT INTO DST DBRA D2,stMASK2 ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment ;------------------------------------------------------- ; ; MODE 3 OR 7: SRC BIC DST --> DST ; ; ASSUME SRC IS EXPANDED BLACK/WHITE PATTERN. SRC IS USED ; TO PUNCH DST, BK APPLIED TO SRC, THEN COMBINED WITH DST. ; stMASK3 if 0 then lea stMASK3NoColorize,a0 ;assume no colorizing ; ; should we colorize here? ; btst #ColorizeInModeCaseBit,XLateFlag(a6) bne.s @goslow @RememberAndDoIt move.l a0,ModeCase(a6) jmp (a0) @goSlow lea stMASK3Colorize,a0 ;shift, invert, and colorize bra.s @RememberAndDoIt endif stMASK3Colorize BFEXTU (A3){D6:0},D0 ;get an aligned long from bitmap ADD #4,A3 ;bump to next long of source EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET MOVE.L (A2)+,D1 ;GET MASK AND.L D1,D0 ;MASK SRC MOVE.L D0,D1 ;COPY MASKED SRC AND.L D4,D1 ;AND SRC WITH BG COLOR (FOR BIC) NOT.L D0 ;GET BITS THAT AREN'T BIC'ED AND.L (A4),D0 ;GET DST THAT DOESN'T CHANGE OR.L D1,D0 ;FORM SRC BIC DST MOVE.L D0,(A4)+ ;AND PUT TO DST DBRA D2,stMASK3Colorize ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW if 0 then stMASK3NoColorize BFEXTU (A3){D6:0},D0 ;get an aligned long from bitmap ADD #4,A3 ;bump to next long of source EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET MOVE.L (A2)+,D1 ;GET MASK AND.L D1,D0 ;MASK SRC MOVE.L D0,D1 ;COPY MASKED SRC NOT.L D0 ;GET BITS THAT AREN'T BIC'ED AND.L (A4),D0 ;GET DST THAT DOESN'T CHANGE OR.L D1,D0 ;FORM SRC BIC DST MOVE.L D0,(A4)+ ;AND PUT TO DST DBRA D2,stMASK3NoColorize ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW endif ; note that arithmetic modes expect the destination pixel size instead of the invert state in D7 ALIGN Alignment stAddOver @loopTop ADD.L D7,D6 ;bump source pointer BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap LEA red(A5,D0*8),A0 ;figure out where it lives in the color table BFEXTU (A4){D3:D7},D0 ;a pixel of the destination LEA red(A5,D0*8),A1 ;figure out where destination lives MOVE (A0)+,D0 ;red get source color value ADD (A1)+,D0 ; combine source and destination ASL.L D5,D0 ; save the top bits in the top word MOVE (A0)+,D0 ;green get source color value ADD (A1)+,D0 ; combine source and destination ASL.L D5,D0 ; save the top bits in the top word MOVE (A0)+,D0 ;blue get source color value ADD (A1)+,D0 ; combine source and destination ASL.L D5,D0 ; save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment stAddPin @loopTop ADD.L D7,D6 ;bump source pointer BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap LEA red(A5,D0*8),A0 ;figure out where it lives in the color table BFEXTU (A4){D3:D7},D0 ;a pixel of the destination LEA red(A5,D0*8),A1 ;figure out where destination lives MOVE (A0)+,D0 ;red get source color value ADD (A1)+,D0 ; combine source and destination BCS.S @tooBigRed CMP pin+4(A6),D0 ; bigger than pin value? BLS.S @notTooBigRed ; no, no problem @tooBigRed MOVE pin+4(A6),D0 @notTooBigRed ASL.L D5,D0 ;save the top bits in the top word MOVE (A0)+,D0 ;green get source color value ADD (A1)+,D0 ; combine source and destination BCS.S @tooBigGreen CMP pin+2(A6),D0 ; bigger than pin value? BLS.S @notTooBigGreen ; no, no problem @tooBigGreen MOVE pin+2(A6),D0 @notTooBigGreen ASL.L D5,D0 ;save the top bits in the top word MOVE (A0)+,D0 ;blue get source color value ADD (A1)+,D0 ; combine source and destination BCS.S @tooBigBlue CMP pin(A6),D0 ; bigger than pin value? BLS.S @notTooBigBlue ; no, no problem @tooBigBlue MOVE pin(A6),D0 @notTooBigBlue ASL.L D5,D0 ;save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment stSubOver @loopTop ADD.L D7,D6 ;bump source pointer BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap LEA red(A5,D0*8),A0 ;figure out where it lives in the color table BFEXTU (A4){D3:D7},D0 ;a pixel of the destination LEA red(A5,D0*8),A1 ;figure out where destination lives MOVE (A1)+,D0 ;red get destination color value SUB (A0)+,D0 ; less source ASL.L D5,D0 ; save the top bits in the top word MOVE (A1)+,D0 ;green get destination color value SUB (A0)+,D0 ; less source ASL.L D5,D0 ; save the top bits in the top word MOVE (A1)+,D0 ;blue get destination color value SUB (A0)+,D0 ; less source ASL.L D5,D0 ; save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment stSubPin @loopTop ADD.L D7,D6 ;bump source pointer BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap LEA red(A5,D0*8),A0 ;figure out where it lives in the color table BFEXTU (A4){D3:D7},D0 ;a pixel of the destination LEA red(A5,D0*8),A1 ;figure out where destination lives MOVE (A1)+,D0 ;red get destination color value SUB (A0)+,D0 ; less source BCS.S @tooSmallRed CMP pin+4(A6),D0 ; smaller than pin value? BHS.S @notTooSmallRed ; no, no problem @tooSmallRed MOVE pin+4(A6),D0 @notTooSmallRed ASL.L D5,D0 ;save the top bits in the top word MOVE (A1)+,D0 ;green get destination color value SUB (A0)+,D0 ; less source BCS.S @tooSmallGreen CMP pin+2(A6),D0 ; smaller than pin value? BHS.S @notTooSmallGreen ; no, no problem @tooSmallGreen MOVE pin+2(A6),D0 @notTooSmallGreen ASL.L D5,D0 ;save the top bits in the top word MOVE (A1)+,D0 ;blue get destination color value SUB (A0)+,D0 ; less source BCS.S @tooSmallBlue CMP pin(A6),D0 ; smaller than pin value? BHS.S @notTooSmallBlue ; no, no problem @tooSmallBlue MOVE pin(A6),D0 @notTooSmallBlue ASL.L D5,D0 ;save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment stMax @loopTop ADD.L D7,D6 ;bump source pointer BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap LEA red(A5,D0*8),A0 ;figure out where it lives in the color table BFEXTU (A4){D3:D7},D0 ;a pixel of the destination LEA red(A5,D0*8),A1 ;figure out where destination lives MOVE (A0)+,D0 ;red get source color value CMP (A1),D0 ; compare source and destination BHS.S @gotTheMaxRed MOVE (A1),D0 @gotTheMaxRed ADDQ #2,A1 ASL.L D5,D0 ; save the top bits in the top word MOVE (A0)+,D0 ;green get source color value CMP (A1),D0 ; compare source and destination BHS.S @gotTheMaxGreen MOVE (A1),D0 @gotTheMaxGreen ADDQ #2,A1 ASL.L D5,D0 ; save the top bits in the top word MOVE (A0)+,D0 ;blue get source color value CMP (A1),D0 ; compare source and destination BHS.S @gotTheMaxBlue MOVE (A1),D0 @gotTheMaxBlue ASL.L D5,D0 ; save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment stMin @loopTop ADD.L D7,D6 ;bump source pointer BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap LEA red(A5,D0*8),A0 ;figure out where it lives in the color table BFEXTU (A4){D3:D7},D0 ;a pixel of the destination LEA red(A5,D0*8),A1 ;figure out where destination lives MOVE (A0)+,D0 ;red get source color value CMP (A1),D0 ; compare source and destination BLS.S @gotTheMinRed MOVE (A1),D0 @gotTheMinRed ADDQ #2,A1 ASL.L D5,D0 ; save the top bits in the top word MOVE (A0)+,D0 ;green get source color value CMP (A1),D0 ; compare source and destination BLS.S @gotTheMinGreen MOVE (A1),D0 @gotTheMinGreen ADDQ #2,A1 ASL.L D5,D0 ; save the top bits in the top word MOVE (A0)+,D0 ;blue get source color value CMP (A1),D0 ; compare source and destination BLS.S @gotTheMinBlue MOVE (A1),D0 @gotTheMinBlue ASL.L D5,D0 ; save the top bits in the top word SWAP D0 ;r, g, b in high word MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment stAvg @loopTop ADD.L D7,D6 ;bump source pointer BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap LEA red(A5,D0*8),A0 ;figure out where it lives in the color table BFEXTU (A4){D3:D7},D0 ;a pixel of the destination LEA red(A5,D0*8),A1 ;figure out where destination lives MOVEQ #2,D1 ;do three times MOVE invSize(A6),D5 ;do once for r, b and g ADD D5,D5 ;initialize at 2x for shift count CLR -(SP) ;make space & initialize average r, b, g @nextColor MOVE (A0)+,D0 ;get source color value MULU (weight,A6,D1*2),D0 ;weight varies from 0 to 1 MOVE (A1)+,D4 ;get destination value MULU (notWeight,A6,D1*2),D4 ;weight varies from 1 to 0 ADD.L D4,D0 ;combine them SWAP D0 ;high word is interesting part MOVE rtShift(A6),D4 ;amount to shift right LSR D4,D0 ;get top bits only LSL D5,D0 ;shift by 2x, 1x, or 0 (for r, g, & b) OR D0,(SP) ;combine r, g, b SUB invSize(A6),D5 ;decrement shift, weight index DBRA D1,@nextColor ;do for b & g as well MOVE (SP)+,D0 ;r, g, b MOVE.B ([invColor,A6],D0,itTable),D0 ;get the pixel value of the additive sum BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ALIGN Alignment stTransparent @loopTop ADD.L D7,D6 ;bump source pointer @loopTop1 BFEXTU (A3){D6:0},D0 ;get a long from the source CMP.L D0,D4 ;same as the background? BEQ.S @skipLong BFEXTU (A2){D3:D7},D0 ;get a pixel of mask BEQ.S @skip ;if none, skip the pixel BFEXTU (A3){D6:D7},D0 ;get a pixel from bitmap CMP.L D0,A5 ;same as a pixel of the background? BEQ.S @skip BFINS D0,(A4){D3:D7} ;move to the destination @skip ADD.L D7,D3 ;advance to next destination DBRA D2,@loopTop ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW @skipLong ADDQ #4,A3 ;bump the source by a long ADD #32,D3 ;bump mask and destination SUB D5,D2 ;a long’s worth of pixels BGE.S @loopTop1 MOVE.L bColor(A6),D4 ;set up colorMap backcolor for skipping coloring source BRA NEXTDST ALIGN Alignment ; from QDciPatchROM.a verbatim 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 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 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 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 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 stb QUADColor move.l fcolor(a6),d3 move.l bcolor(a6),d4 SUB.L A1,A2 ;Get byte count MOVE.L A2,D1 ; LSR.L #2,D1 ;Get count of longs SUBQ #1,D1 ;less one for the dbra @4 MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC MOVE.L TABLE4(D0*4),D2 ;convert to a 4 bit/pixel ; ;colorize ; MOVE.L D2,D5 ;copy of source NOT.L D2 ;turn on background bits AND.L D3,D5 ;color same as background color AND.L D4,D2 ;color foreground bits same as foreground color OR.L D5,D2 ;combine colored foreground and background bits move.l d2,(A1)+ ;AND SPIT OUT A LONG DBRA D1,@4 ;IS DSTPTR >= DSTLIMIT ? RTS ;ALL DONE ; QUAD INTO A LONG FOR PATTERNS QUAD1 CLR.W (A1)+ ;CLEAR PATROW CLR.L (A1)+ ;CLEAR PATHMASK, PATVMASK MOVE.L (A1),A1 ;GET EXPAT POINTER moveq #0,d0 MOVE.B (A0)+,D0 ;GET First BYTE OF PATTERN bra.s @first @0 MOVEQ #0,D0 ;CLEAR OUT HIGH PART MOVE.B (A0)+,D0 ;GET A BYTE OF PATTERN cmp.b D5,D0 ;Same as last time? beq.s @again @first move.b D0,D5 ;cache for later EOR.B D7,D0 ;INVERT IT IF MODE BIT 2 ROL.B D2,D0 ;ALIGN TO LOCAL COORDS MOVE.L TABLE4(D0*4),D1 ;PUT A LONG TO D1 MOVE.L D1,D0 ;COPY FOR NOTMASK AND.L D3,D0 ;GET LONG OF FG DATA NOT.L D1 ;GET NOTMASK AND.L D4,D1 ;GET LONG OF BK DATA OR.L D0,D1 ;COMBINE THEM @again MOVE.L D1,(A1)+ ;PUT A LONG MOVE.L D1,32-4(A1) ;PUT ANOTHER LONG DBRA D6,@0 ;REPEAT FOR EACH BYTE RTS ;ALL DONE ALIGN 4 TABLE4 DC.L $00000000,$0000000F,$000000F0,$000000FF ;QUADRUPLING TABLE DC.L $00000F00,$00000F0F,$00000FF0,$00000FFF DC.L $0000F000,$0000F00F,$0000F0F0,$0000F0FF DC.L $0000FF00,$0000FF0F,$0000FFF0,$0000FFFF DC.L $000F0000,$000F000F,$000F00F0,$000F00FF ;QUADRUPLING TABLE DC.L $000F0F00,$000F0F0F,$000F0FF0,$000F0FFF DC.L $000FF000,$000FF00F,$000FF0F0,$000FF0FF DC.L $000FFF00,$000FFF0F,$000FFFF0,$000FFFFF DC.L $00F00000,$00F0000F,$00F000F0,$00F000FF ;QUADRUPLING TABLE DC.L $00F00F00,$00F00F0F,$00F00FF0,$00F00FFF DC.L $00F0F000,$00F0F00F,$00F0F0F0,$00F0F0FF DC.L $00F0FF00,$00F0FF0F,$00F0FFF0,$00F0FFFF DC.L $00FF0000,$00FF000F,$00FF00F0,$00FF00FF ;QUADRUPLING TABLE DC.L $00FF0F00,$00FF0F0F,$00FF0FF0,$00FF0FFF DC.L $00FFF000,$00FFF00F,$00FFF0F0,$00FFF0FF DC.L $00FFFF00,$00FFFF0F,$00FFFFF0,$00FFFFFF DC.L $0F000000,$0F00000F,$0F0000F0,$0F0000FF ;QUADRUPLING TABLE DC.L $0F000F00,$0F000F0F,$0F000FF0,$0F000FFF DC.L $0F00F000,$0F00F00F,$0F00F0F0,$0F00F0FF DC.L $0F00FF00,$0F00FF0F,$0F00FFF0,$0F00FFFF DC.L $0F0F0000,$0F0F000F,$0F0F00F0,$0F0F00FF ;QUADRUPLING TABLE DC.L $0F0F0F00,$0F0F0F0F,$0F0F0FF0,$0F0F0FFF DC.L $0F0FF000,$0F0FF00F,$0F0FF0F0,$0F0FF0FF DC.L $0F0FFF00,$0F0FFF0F,$0F0FFFF0,$0F0FFFFF DC.L $0FF00000,$0FF0000F,$0FF000F0,$0FF000FF ;QUADRUPLING TABLE DC.L $0FF00F00,$0FF00F0F,$0FF00FF0,$0FF00FFF DC.L $0FF0F000,$0FF0F00F,$0FF0F0F0,$0FF0F0FF DC.L $0FF0FF00,$0FF0FF0F,$0FF0FFF0,$0FF0FFFF DC.L $0FFF0000,$0FFF000F,$0FFF00F0,$0FFF00FF ;QUADRUPLING TABLE DC.L $0FFF0F00,$0FFF0F0F,$0FFF0FF0,$0FFF0FFF DC.L $0FFFF000,$0FFFF00F,$0FFFF0F0,$0FFFF0FF DC.L $0FFFFF00,$0FFFFF0F,$0FFFFFF0,$0FFFFFFF DC.L $F0000000,$F000000F,$F00000F0,$F00000FF ;QUADRUPLING TABLE DC.L $F0000F00,$F0000F0F,$F0000FF0,$F0000FFF DC.L $F000F000,$F000F00F,$F000F0F0,$F000F0FF DC.L $F000FF00,$F000FF0F,$F000FFF0,$F000FFFF DC.L $F00F0000,$F00F000F,$F00F00F0,$F00F00FF ;QUADRUPLING TABLE DC.L $F00F0F00,$F00F0F0F,$F00F0FF0,$F00F0FFF DC.L $F00FF000,$F00FF00F,$F00FF0F0,$F00FF0FF DC.L $F00FFF00,$F00FFF0F,$F00FFFF0,$F00FFFFF DC.L $F0F00000,$F0F0000F,$F0F000F0,$F0F000FF ;QUADRUPLING TABLE DC.L $F0F00F00,$F0F00F0F,$F0F00FF0,$F0F00FFF DC.L $F0F0F000,$F0F0F00F,$F0F0F0F0,$F0F0F0FF DC.L $F0F0FF00,$F0F0FF0F,$F0F0FFF0,$F0F0FFFF DC.L $F0FF0000,$F0FF000F,$F0FF00F0,$F0FF00FF ;QUADRUPLING TABLE DC.L $F0FF0F00,$F0FF0F0F,$F0FF0FF0,$F0FF0FFF DC.L $F0FFF000,$F0FFF00F,$F0FFF0F0,$F0FFF0FF DC.L $F0FFFF00,$F0FFFF0F,$F0FFFFF0,$F0FFFFFF DC.L $FF000000,$FF00000F,$FF0000F0,$FF0000FF ;QUADRUPLING TABLE DC.L $FF000F00,$FF000F0F,$FF000FF0,$FF000FFF DC.L $FF00F000,$FF00F00F,$FF00F0F0,$FF00F0FF DC.L $FF00FF00,$FF00FF0F,$FF00FFF0,$FF00FFFF DC.L $FF0F0000,$FF0F000F,$FF0F00F0,$FF0F00FF ;QUADRUPLING TABLE DC.L $FF0F0F00,$FF0F0F0F,$FF0F0FF0,$FF0F0FFF DC.L $FF0FF000,$FF0FF00F,$FF0FF0F0,$FF0FF0FF DC.L $FF0FFF00,$FF0FFF0F,$FF0FFFF0,$FF0FFFFF DC.L $FFF00000,$FFF0000F,$FFF000F0,$FFF000FF ;QUADRUPLING TABLE DC.L $FFF00F00,$FFF00F0F,$FFF00FF0,$FFF00FFF DC.L $FFF0F000,$FFF0F00F,$FFF0F0F0,$FFF0F0FF DC.L $FFF0FF00,$FFF0FF0F,$FFF0FFF0,$FFF0FFFF DC.L $FFFF0000,$FFFF000F,$FFFF00F0,$FFFF00FF ;QUADRUPLING TABLE DC.L $FFFF0F00,$FFFF0F0F,$FFFF0FF0,$FFFF0FFF DC.L $FFFFF000,$FFFFF00F,$FFFFF0F0,$FFFFF0FF DC.L $FFFFFF00,$FFFFFF0F,$FFFFFFF0,$FFFFFFFF ALIGN Alignment ;----------------------------------------------- ; ; STRETCH BY SIX USING TABLE LOOKUP ; SIX MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC MOVE D0,D1 ;MAKE AN EXTRA COPY AND #$E0,D1 ;MASK FOR HI 3 BITS LSR.B #4,D1 ;SHIFT FOR TABLE INDEX MOVE.W TABLE6A(D1),(A1)+ ;PUT A WORD TO DST MOVE D0,D1 ;GET SRC BYTE AGAIN AND #$3C,D1 ;MASK FOR MIDDLE 4 BITS LSR.B #1,D1 ;SHIFT FOR TABLE INDEX MOVE.W TABLE6B(D1),(A1)+ ;PUT A WORD TO DST MOVE D0,D1 ;GET SRC BYTE AGAIN AND #7,D1 ;MASK FOR LO 3 BITS ADD D1,D1 ;DOUBLE FOR TABLE INDEX MOVE.W TABLE6C(D1),(A1)+ ;PUT A WORD TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO SIX ;NO, LOOP FOR MORE RTS ;ALL DONE TABLE6A DC.W $0000,$000F,$03F0,$03FF ;SIX TIMES TABLE DC.W $FC00,$FC0F,$FFF0,$FFFF TABLE6B DC.W $0000,$0003,$00FC,$00FF DC.W $3F00,$3F03,$3FFC,$3FFF DC.W $C000,$C003,$C0FC,$C0FF DC.W $FF00,$FF03,$FFFC,$FFFF TABLE6C DC.W $0000,$003F,$0FC0,$0FFF DC.W $F000,$F03F,$FFC0,$FFFF ALIGN Alignment ; EXPAND AN 8*8 PATTERN FOR EIGHT BITS PER PIXEL EIGHT1 MOVE #8,(A1)+ ;PATROW = 8 MOVE #$0004,(A1)+ ;PATHMASK = $0004 MOVE #$003F,(A1)+ ;PATVMASK = $003F ; IF PATTERN REPEATS ITSELF, THEN DO OLD WAY FOR SPEED. MOVE.L A0,A2 ;COPY PATTERN POINTER MOVEQ #7,D0 ;DO EIGHT BYTES @0 MOVE.B (A2),D1 ;GET A BYTE ROR.B #4,D1 ;SWAP NIBBLES CMP.B (A2)+,D1 ;ARE THEY THE SAME? DBNE D0,@0 ;REPEAT FOR 8 BYTES BNE.S @1 ;=>NO, DO NEW WAY CLR -6(A1) ;AND SET PATROW = 0 BRA.S Small8 ;Pattern is in 1 long wide @1 MOVE.L (A1),A1 ;GET EXPAT POINTER FULL8 MOVEQ #0,D1 ;MAKE SURE HIGH PART IS 0 MOVE.B (A0)+,D1 ;GET A BYTE OF PATTERN EOR.B D7,D1 ;INVERT IT IF MODE BIT 2 ROL.B D2,D1 ;ALIGN TO LOCAL COORDS MOVE D1,D5 ;SAVE IN D5 AND #$F0,D1 ;MASK FOR HI NIBBLE LSR #2,D1 ;SHIFT FOR TABLE INDEX MOVE.L TABLE8(D1),D1 ;PUT FIRST LONG TO DST MOVE.L D1,D0 ;COPY FOR NOTMASK AND.L D3,D0 ;GET LONG OF FG DATA NOT.L D1 ;GET NOTMASK AND.L D4,D1 ;GET LONG OF BK DATA OR.L D0,D1 ;COMBINE THEM MOVE.L D1,(A1)+ ;PUT A LONG AND #$0F,D5 ;MASK FOR LO NIBBLE MOVE.L TABLE8(D5*4),D1 ;PUT SECOND LONG TO DST MOVE.L D1,D0 ;COPY FOR NOTMASK AND.L D3,D0 ;GET LONG OF FG DATA NOT.L D1 ;GET NOTMASK AND.L D4,D1 ;GET LONG OF BK DATA OR.L D0,D1 ;COMBINE THEM MOVE.L D1,(A1)+ ;PUT A LONG DBRA D6,FULL8 ;REPEAT FOR EACH LONG RTS ;ALL DONE Small8 MOVE.L (A1),A1 ;GET EXPAT POINTER moveq #0,d0 MOVE.B (A0)+,D0 ;GET First BYTE OF PATTERN bra.s @first @NXT8 MOVEQ #0,D0 ;MAKE SURE HIGH PART IS 0 MOVE.B (A0)+,D0 ;GET A BYTE OF PATTERN cmp.b D5,D0 ;Same as last time? beq.s @again @first move.b D0,D5 ;cache for later EOR.B D7,D0 ;INVERT IT IF MODE BIT 2 ROL.B D2,D0 ;ALIGN TO LOCAL COORDS AND #$F0,D0 ;MASK FOR HI NIBBLE LSR #2,D0 ;SHIFT FOR TABLE INDEX MOVE.L TABLE8(D0),D1 ;PUT FIRST LONG TO DST MOVE.L D1,D0 ;COPY FOR NOTMASK AND.L D3,D0 ;GET LONG OF FG DATA NOT.L D1 ;GET NOTMASK AND.L D4,D1 ;GET LONG OF BK DATA OR.L D0,D1 ;COMBINE THEM @again MOVE.L D1,(A1)+ ;PUT A LONG MOVE.L D1,32-4(A1) ;MAKE 2 COPIES DBRA D6,@NXT8 ;REPEAT FOR EACH LONG RTS ;ALL DONE ALIGN 4 ;MOVED TABLE TO KEEP TABLE IN RANGE <22> TABLE8 DC.L $00000000,$000000FF,$0000FF00,$0000FFFF DC.L $00FF0000,$00FF00FF,$00FFFF00,$00FFFFFF DC.L $FF000000,$FF0000FF,$FF00FF00,$FF00FFFF DC.L $FFFF0000,$FFFF00FF,$FFFFFF00,$FFFFFFFF ALIGN Alignment ;----------------------------------------------- ; ; SCALE UP BY EIGHT USING TABLE LOOKUP ; Eight MOVE.B (A0)+,D0 ;GET A BYTE OF SRC MOVE D0,D1 ;MAKE AN EXTRA COPY AND #$F0,D1 ;MASK FOR HI NIBBLE LSR #2,D1 ;SHIFT FOR TABLE INDEX MOVE.L TABLE8(D1),(A1)+ ;PUT FIRST LONG TO DST AND #$0F,D0 ;MASK FOR LO NIBBLE MOVE.L TABLE8(D0*4),(A1)+ ;PUT second LONG TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO.s Eight ;NO, GO FOR MORE RTS ;ALL DONE ALIGN Alignment ;----------------------------------------------- ; ; SCALE UP BY EIGHT USING TABLE LOOKUP, then colorize ; ; from QDciPatchROM.a but doesn’t use A3 here 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. 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. 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) ; 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 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 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) ; 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? beq.s averageH16 ;yes, average 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 ----------------------- ; ;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) 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 @@@@ 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 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 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 move.b (a5,d1),d1 ; get actual luminance as a word sub.w d1,d7 ; get luminance error as a word 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 sub.w d0,d7 ; get luminance error as a word 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 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 move.b (a5,d1),d1 ; get actual luminance as a word sub.w d1,d7 ; get luminance error as a word 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 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 sub.w d0,d7 ; get luminance error as a word 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 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 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 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 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 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 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 ; from QDciPatchROM.a verbatim 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 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 ; 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 rts ; from QDciPatchROM.a verbatim 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 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 @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 @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 MOVE.L (A5),D0 ;compute output cache value MOVE.B D0,D7 ;map 1st byte LSL.L #8,D7 ; MOVE.B D0,D7 ;map 2nd byte MOVE.W D7,D0 ;get 2 mapped bytes SWAP D7 ; MOVE.W D0,D7 ;map 3rd and 4th bytes 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 @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 BEQ.s @a ;if white->white, ok 12Jul88 MOVEQ #$F,D0 ;else, its black 12Jul88 @a ; 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> ;****************************************************************************************** ;******************************************************************************************