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

19650 lines
658 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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

;
; File: QDciPatchROM.a
;
; Contains: Quickdraw patches for ci and descendents
;
; Written by: Konstantin Othmer
;
; Copyright: © 1990-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM5> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
; so they can coditionalized out of the build.
; <135> 8/18/92 SAH #1040323 <KON>: Fixed Indexed SeedCFill bug by making
; MakeScaleTbl check to see if fg color is black and bg color is
; white before it inverts the bg color when drawing to a one bit
; destination.
; <134> 6/25/92 SAH #1033729: Fixed a bug where we did not fully recognize when we
; were drawing to the alpha channel just before we jump into
; ScaleBlt. We now do this properly and take Stretch if drawing
; alpha stuff, otherwise take ScaleBlt.
; <133> 6/10/92 SAH Fixed problem where we would go to Stretch if ScaleBlt did not
; handle the copy and the source was greater than one bit. This
; was causing crashes in Freehand and Macromind Director.
; Associated with this, fixed problems where StkLowPt, HiHeapMark
; and your stack were getting munged when StretchBits couldn't get
; all the stack it wanted. Fixed notSrcCopy and SearchProc
; problems in MakeScaleTbl.
; <132> 6/8/92 SAH #1031825: Changed StretchBits so that it calls ScaleBlt whenever
; possible (indexed to indexed and indexed to direct). If the
; source is black/white only (from multColor), take BitBlt
; whenever source and dest are same depths and change ScaleColor
; to ColorizeInModeCase. Brought in Kon's changes for deciding
; when colorizing is a no-op.
; <131> 5/5/92 SAH Put fix for clipped vertical stretch back in for Cube-E
; <130> 4/10/92 SAH Moved the bSetup0 patch from this file to QuickDrawPatches.a.
; <129> 2/18/92 DTY Pete, ybroke the dang build! :)
; <128> 2/18/92 pvh Leave out bSETUP0 (questionable MOVE16 patch) to save a K or so
; of space in the System.
; <127> 2/17/92 pvh Removed QD patch for MOVE16. Fast blit abandoned for Regatta &
; Cube-E.
; <126> 10/16/91 KON Move some routines over to linked patches so this file can be
; expanded later.
; <125> 10/4/91 JSM Change PsychoticFarmerOrLater conditionals to TheFuture.
; <124> 10/2/91 DTY Conditionalise <122> and <123> for TheFuture.
; <123> 10/2/91 KON Fix bug where CopyBits was crashing when vertically stretching a
; pixmap that is clipped at the top.
; <122> 10/1/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.
; <121> 9/25/91 JSM Change PsychoticFarmerAndLater to PsychoticFarmerOrLater.
; <120> 9/13/91 DTY What was I thinking? (Obviously I wasnt.) Give the If a Then to
; keep it company.
; <119> 9/13/91 DTY Dont build <117> for CubeE. (The optimization will build for
; PsychoticFarmer.)
; <118> 8/23/91 JSM Remove benign redefinition of TRUE and FALSE, which are now
; defined by the build script.
; <117> 7/23/91 KON Put in optimization for colorized text. If scalecase colorizing
; and depths are the same, use bitblt instead of stretch.
; <116> 7/17/91 JSM Remove obsolete SysVers conditionals, remove pre-7.0 code, and
; remove code that was ifdefed for 0.
; <115> 7/10/91 dba end of the forPost70 conditional; we are past 7.0 for good
; <114> 6/14/91 JL Removed benign redefinition of HWCfgFlags declared in Private.a.
; <113> 6/12/91 LN Removed #includes for private interfaces from public interfaces.
; Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a'
; <112> 6/11/91 gbm Take out conditional for Regatta
; <111> 5/30/91 KON Checked in for Eclipse. Fixed most ScaleCase and modecase
; colorizing NOP checks.
; <110> 5/8/91 KON SetCCursor now in RAM because register A2 was getting trashed on
; multiple device systems. Also sped up stretch (right after map
; mode table). Some of the checks to see if colorizing is
; happening were wrong.
; <109> 4/10/91 KON mrr, gbm,csd: Calculate numer and denom to 32-bits, and then
; shift to make it fit in 15-bits if necessary. This fixes the
; problem where text was not scaling uniformly in pictures.
; <108> 4/9/91 KON csd: When reducing a picture, text would not reduce properly
; since both numer and denom are small and the divide underflows.
; The fix is not to reduce numer/denom if the picture is being
; scaled down.
; <107> 4/5/91 KON csd, BRC#85913: When putting a PixPat to a picture, PutPMData is
; called which trashes register A1. With this fix, A1 is saved and
; restored across the call to PutPMData.
; <106> 3/23/91 KON csd, WRKSHT#SAH-QD-58: ReduceD3D4 would hang because MapRatio
; would return a zero result. I removed calls to MapRatio (since
; ReduceD3D4 does the same work) and changed ReduceD3D4 so it
; won't hang.
; <105> 3/22/91 KON CSD, WRKSHT#7P-WA-054: Large text does not draw correctly since
; fromRect scaled by numer/denom can overflow a word.
; <104> 3/20/91 KON gbm, WRKSHT#SAH-QD-053: StdOpCodeProc sets the denom of a
; picture created with OpenCpicture. This is a problem since
; DrawPicture reduced numer/denom, and blasting denom to a large
; value makes the fraction invalid. The fix is to reduce
; numer/denom after the header has been processed. Also fixed
; WRKSHT#SAH-QD-056: Test for screen device in overlapping device
; test was backwards.
; <103> 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 removed this feature.
; <102> 3/19/91 KON DTY, CSD: BRC# 84342, Fixing 84342 made this file too big, so we
; removed NewPixMap and BitMapRgn and made them linked patches now
; included in QuickDrawPatches.a.
; <101> 3/18/91 KON GSC: WKSHT# SAH-QD-054 16-bit source shrinks crash because the
; average buffer is calculated from the promoted depth, rather
; than the real depth.
; <100> 3/14/91 JT After rolling in both Konstantine's changes and my own changes
; (build mix-up), this file was just too big to link properly
; (lame linker). Moved the GCD routines to the top of the file so
; that PC-relative references in the "cut back" installation code
; (hack) would be closer to the referenced routines. No one
; checked this change (late night) and there are no BRC or
; Worksheet reference numbers (not approved). Programmer
; Subliminal rides again!
; <99> 3/13/91 JT Added the glyph state opcode support to text and picture drawing
; under new QuickDraw. This opcode records the state of the Font
; Manager and TrueType so text will be drawn the same on picture
; playback as it was during picture recording. Also prevented font
; naming, line layout, and glyph state opcodes from being recorded
; in old pictures. Finally, changed the symbol UpdateRgn in
; ScrollRect to prevent compiler warnings. Code checked by KON and
; BAL. BRC numbers 82651 and 79185. Worksheet number KON-022.
; <98> 3/13/91 SMC CEL, Worksheet #AMR-029: Setup BGnotWhite based on xlateFlags
; before calling rgnblt. It was using whatever happened to be on
; the stack to decide whether or not to colorize.
; <97> 3/13/91 SMC forRegattaCPUs, fixed cpuFlag check in bSetup0 patch to include
; '040 processors and greater.
; <96> 3/6/91 KON CEL: BRC# 84369, WKSHT# B5-MTM-009 Register D0 was getting
; trashed when search procs were attached to direct destinations.
; Also, 32-bit to 16-bit conversion was not correct when modecase
; colorizing and destination is direct. MakeScaleTable began
; search for unused colors at the wrong place in the stack. If
; the value it was looking for happened to be there, that location
; on the stack was getting trashed.
; <95> 2/27/91 KON DTY BRC #82863: Some large text does not print in pictures
; because numer and denom overflow. Here I reduce the scale factor
; (the ratio of the rectangle sides) before scaling numer and
; denom. This prevents the overflow. Also rolled in 040 patches
; conditionalized by forRegattaCPUs. Finally, I now clear the
; dither flag if the destination is larger than the source and the
; color tables are the same. This is forPost70.
; <94> 2/19/91 KON DDG: WorkSheet #KS-003, MaskAddr in the stackframe is not
; initialized if there is not a mask. This was causing crashes in
; some cases since vertical merge scanline routines look at the
; maskaddr.
; <93> 2/4/91 KON DDG: BRC# unknown: PutPicPixPat should call PutDirectPMData for
; direct pixpats.
; <92> 1/25/91 KON DDG: BRC# 81625 and 81626, Add patch to BitsDevLoop to check for
; overlapping screen gDevices. If devices overlap, don't copy
; between them. Fix Bic and notBic transfer modes for
; CopyDeepMask.
; <91> 1/23/91 KON Optimize and clean up code that was rushed for B4. [smc]
; <90> 1/15/91 KON Change OffscreenVersion from 120 to 130. [CEL]
; <89> 1/14/91 KON Fixed pixmaps with nil color tables. Fixed CopyDeepMask when
; the mask is 1-bit. Fix bug in pmVersion macro. [SMC]
; <88> 1/11/91 KON Change updateGWorld so that returned flags get updated. Reduce
; Numer and Denom by GCD when drawing a picture. Fix problem with
; regions that showed up in KeyCaps. [CEL]
; <87> 12/13/90 KON If color table NIL on PixMap record into picture, put special
; color table with signature. On Picture playback, check for color
; table signature before throwing it away. [smc]
; <86> 12/3/90 KON Color Table in pictures, take three. If color table is NIL on
; picture creation, put a minimal color table to the picture.
; Always read color table in on playback; if it was nil in the PM
; record then throw it away. [smc]
; <85> 11/28/90 SMC Fixed slab/stretch/rgnblt pattern hiliting and fixed problem
; with L-shaped polygons getting optimized out as rectangles.
; With BAL.
; <84> 11/13/90 KON Fix problem with colorizing when dithering from an indexed src
; to an indexed destination. [smc]
; <83> 11/13/90 JSM <dba> ifdef come-from patch on _StdTxMeas inside GetRect for
; pre-7.0 only (the entire GetRect routine is patched out in 7.0),
; move the following patches to QuickDrawPatches.a: come-from
; patch on _PackBits inside PutPMData, come-from patch on
; _CopyBits inside CopyBits, come-from patch on _GetMaxDevice
; inside NewGWorld and NewTempScreenBuffer, come-from patch on
; _DisposeGWorld inside UpdateGWorld.
; <82> 11/12/90 KON Stretch now copies input rectangles and negative pmVersion
; pixmaps work. [smc]
; <81> 11/6/90 gbm the fact that change #80 broke the build with an assembly error
; was all Konstantins fault, really. My initials were on it, but
; I really didnt have anything to do with it. (with sab)
; <80> 11/6/90 gbm All patches to picitem1 assume the result will be non-zero.
; Centralize this so that each opcode proc doesn't need to set
; this individually. [KON]
; <79> 11/6/90 SMC Fixed pattern alignment problem in QuickerDraw slab copy (KON).
; <78> 11/6/90 KON GetCTable should return NIL if call fails. This is at an offset
; of 6, not 8.
; <77> 10/31/90 SMC Added patches for alpha channel fixes with BAL.
; <76> 10/30/90 KON If color table is nil, don't save it to the picture. [SMC]
; <75> 10/29/90 KON If GetCTable fails, it should return NIL. There were cases where
; it returned without setting the return value at all. NewPixMap
; should always return an hres, vres value of 72.
; <74> 10/21/90 KON Move 16-bit and 32-bit arithmetic transfer modes to RAM. They
; are only about 1500 bytes and, unfortunately end with a hard
; branch to ROM. Made BitMapRgn create 64K rgns and accept
; pmVersion=4. Got rid of warning from the dandy new 3.2
; assembler.
; <73> 10/8/90 SMC Fixed pattern hilite setup for 16 and 32-bit slabbing.
; <72> 10/8/90 SMC Patched bTransparent and rTransparent to remove an optimization
; that was losing pattern data. Related changes in Arith8Blt.a.
; <71> 10/8/90 SMC Fixed right edge problem in bSubOver16.
; <70> 10/3/90 KON Change comefrom patch on packbits to check return address as a6
; relative instead of a7 relative since stdpixpat routine long
; aligns the stack.
; <69> 9/27/90 SMC Use common code to patch out specific entries in blit-loop
; offset tables. Also, fixed problem of sc32To8Dither not really
; getting hooked into RAMscDirTab8.
; <68> 9/25/90 KON Don't dither if source is 1-bit b&w and no resizing. Also fixed
; bug with StdOval introduced in last version. (With SMC).
; <67> 9/23/90 KON Patch standard drawing routines to call a new putpicverb which
; calls a new updatepat so CPictures can be created in old style
; ports.
; <66> 9/18/90 SMC Added fix to GetCPixel patch so it returns valid colors along
; the left and top edges of a gdevice.
; <65> 9/18/90 SMC Fixed Transparent, addMax, subOver, addMin pattern transfers.
; <64> 9/18/90 BG Removed <45> (and <46>). 040s are behaving more reliably now.
; <63> 9/16/90 KON NEEDED FOR BETA: Fix problem with saving pixpats into pictures.
; The fix is a comefrom putpicdata on packbits. It's a nasty fix.
; <62> 9/14/90 SMC Fixed problem bSloHilite where the background color was getting
; set to white after the first scanline hilited. This patch also
; includes changes made to stretch to handle vertically aligned
; hiliting.
; <61> 9/13/90 KON NEEDED FOR BETA: Fix problem where promoting pixmaps for dither
; and deep copymask didn't work since register D3 was not setup
; before call to SetupStretch.
; <60> 9/10/90 KON Added comefrom PaintVector patch to BitstoPix so that if the
; VCount in PaintVector is 0, the routine aborts.
; <59> 9/10/90 KON Fix one-bit to one-bit colorize copy.
; <58> 9/7/90 KON Patch MapRgn to return immediately if the region is wide open
; and rectangular.
; <57> 9/6/90 KON Fix stretching bugs and update to coincide with MacII stretch
; (always call search procs, search proc color is a VAR).
; <56> 8/29/90 KON Fix bug in GetMaxDevice ptch.
; <55> 8/28/90 KON Fix search procs so they are always called and treat RGB color
; passed as a VAR. Also added 32-bit clean versions of MaskPix
; pmTable and SrcPix pmTable to stretch stack frame. Fixed
; pictures so packtype 1 pixmaps can be saved in pictures. Fixed
; GetMaxDevice so it calls proper param error routine.
; <54> 8/24/90 PKE (per JT) Use new Script Mgr line layout values in GrafGlobals
; instead of soon-to-be-obsolete values in Script Mgr globals. Use
; new names picQdChExtra and picQdRunSlop instead of picSMgrChar
; and picSMgrSlop. Also deleted duplicate definition of
; PutPicWord.
; <53> 8/20/90 SMC Patched rXMASK8 to deal with the pattern offset as a unsigned
; instead of signed number.
; <52> 8/17/90 KON Fix transparent mode when it goes through stretch. Don't
; colorize arithmetic modes. Don't install DelSearch and DelComp
; on Erickson since the fix is in the ROM. This is not a misprint.
; <52> 8/17/90 KON Fix transparent mode when it goes through stretch. Don't
; colorize arithmetic modes.
; <51> 8/16/90 dba get rid of VisRgnChanged
; <50> 8/3/90 gbm axe warnings, again
; <49> 8/1/90 SMC Made more changes to non-black pattern and source hiliting blit
; loop patch (rSlowHilite) so that 16 and 32-bit cases work.
; <48> 7/31/90 SMC Fix RgnBlt so non-black patterned and source hiliting works.
; <47> 7/30/90 KON Roll over new versions of Stretch, MakeScaleTable, ColorMap,
; BitBlt.
; <46> 7/25/90 gbm took out local Macro def for EclipseNOP... BigBang breaks, big
; time. Also got rid of a couple of warnings...
; <45> 7/25/90 BG Added some EclipseNOPs for flakey 040s.
; <44> 7/24/90 KON Zero pmVersion after getting devices pixmap in PatConvert incase
; it's a gWorld and pmVersion was set indicating the baseAddr is a
; handle.
; <43> 7/20/90 gbm Change a few identifiers, just for the hell of it.
; <42> 7/16/90 DDG Fixed strange change history header; there were two <40> changes
; and this can screw up some of my scripts.
; <41> 7/11/90 gbm waste some asm warnings
; <40> 7/10/90 JT Some kind of PG&E fiasco here. Making sure this really gets
; checked in. Changes for <39> are not needed for SixPack, repeat
; not needed for SixPack.
; <39> 7/9/90 JT Remember to set the result to true after processing a line
; layout picture opcode in the PicItem1 patch. If we don't set
; this then the DrawPicture routine will stop processing the
; picture after encountering the line layout opcode, even if
; there is more interesting stuff in the picture. Special
; apologies to Konstantin Othmer and Peter Edberg. I accept full
; responsibility.
; <38> 6/30/90 DDG NEEDED FOR SIXPACK: Fixed another problem with trap $AB81. This
; really fixes the problem with the Color Picker introduced in rev
; 22.
; <37> 6/29/90 KON NEEDED FOR SIXPACK: Fixed entry point to trap $AB81. This
; fixes problem in Color Picker introduced in rev 22.
; <36> 6/29/90 KON Changed the order the fields in the picSave record or
; initialized to reflect changes in ColorEqu.a.
; <35> 6/27/90 KON Always clear the script manager state information in a picture
; save record.
; <34> 6/25/90 KON Obscure-show-hide leaves crsr hidden only, Obscure-hide-show
; leaves crsr obscured only.
; <33> 6/22/90 KON Ptch'd getPixel and GetCPixel so they work with 32-bit addressed
; pixmaps (pmVersion=4). Fixed NewGWorld so when called with
; noNewDevice bit set, the depth is taken from theGDevice.
; <32> 6/20/90 CL Took out rswapmmumode macro since it now exists in qdhooks.a.
; <31> 6/6/90 KON Change DelSearch and DelComp so Translate24to32 is called on the
; address. Added copymask with mode and rgn parameter. Added
; comeFrom GWorld calls ptch to GetMaxDevice to check for NIL
; devices.
; <30> 5/22/90 KON Fixed UpdateGWorld by patching DisposeGWorld so that the saved
; GWorld pointer and GDevice are updated before the GWorld is
; disposed.
; <29> 5/2/90 JT Copied the Script Manager specific changes from DrawPicture to
; this patch set.
; <28> 4/25/90 csd with BAL: changed the patch to BitsToPix to support the
; needs32BitAddressing flag in D2.
; <27> 3/30/90 KON Fix GetGWorldPixmap so it returns the right result.
; <26> 3/26/90 KON Comefrom patch to StdTxMeas should call through dispatch table
; instead of calling ROM directly. Use NewHandle,sys instead of
; changing theZone. Ptched InvertColor so comp procs work. Added
; VisRgnChanged (trap $A0A5).
; <25> 3/13/90 KON Fix 16-bit search proc.
; <24> 3/6/90 KON Fixed error term for vertical shrinking so expanding and then
; shrinking by an integral amount does not alter the image.
; <23> 3/2/90 KON Patch MakeITable so it looks for memory in Temp memory first,
; then system zone, and finally theZone. Consolidated old
; MakeITable patch which saved the zone. This also required
; patching DisposeTempBuffer to regain control at the end of
; patch.
; <22> 3/1/90 KON Add faster versions of traps AB80, AB81, and AB84 from QDUtil.a.
; This fixes a bug in 8-bit transparent modes.
; <21> 2/26/90 KON Added 16-bit shrink. Added ptch's for Dither32toGray and
; Dither16toGray so the error term is calculated correctly and
; black dots aren't left randomly.
; <20> 2/20/90 KON If LastTxGDevice is the same as the device we are disposing in
; DisposGDevice, move mainDevice into lastTxGDevice.
; <19> 2/16/90 KON NEEDED FOR 6.0.5: Fixed trashed register during shrink.
; <18> 2/15/90 KON Add comefrom patch to StdTxMeas so GetRect multiplies width by
; scaling factor.
; <17> 2/14/90 KON NEEDED FOR 6.0.5: ptch'd OpenPort for baseAddr change, make
; poly's, lines, arcs calc bit offset as long to support large
; rowbytes. This is done as a come-from ptch in GetSeek. Changed
; offscreenVersion to 120. ptch'd stNoStack to try 256K (not 64K),
; and updates StackFree correctly. Memory calculations in stretch
; now use longs.
; <16> 2/12/90 KON NEEDED FOR 6.0.5: Removed references to BaseAddr to support
; gDevices with changing base addresses.
; <15> 2/7/90 KON NEEDED FOR 6.0.5: Fixed 8-bit to 32-bit dither when stretching.
; <14> 2/6/90 KON NEEDED FOR 6.0.5: Changed some PutPicByte calls to DPutPicByte.
; Fixed header in OpenPicture.
; <13> 2/3/90 BAL Rolled in fix to StdBits patch to prevent the baseaddr's of
; non-mainscreens from being stripped by the call to BitsToPix
; during the one screen optimization.
; <12> 2/2/90 KON NEEDED FOR 6.0.5: Check useAverage after expanding in
; stScanLoop. Also took out RecoverHandle because it's patched
; elsewhere now.
; <11> 2/2/90 KON NEEDED FOR 6.0.5: Add ability to record 32-bit addressed pixmaps
; into pictures.
; <10> 2/2/90 KON NEEDED FOR 6.0.5: When recording an old picture flatten source
; pixmaps. Moved DDG's StdBits ptch from GetMaxDevice back into
; StdBits since most of StdBits is now patched out. Changed
; Pixmap32bit to use EXT32Bit gdevice flag. Added ptch to speed up
; CalcCMask and SeedCFill. Ptched Dither16toIndexed to get rid of
; error propagation.
; <9> 1/30/90 DDG NEEDED FOR 6.0.5: Fixed a bug in StdBits by patching out
; GetMaxDevice. The bug would cause pictures being recorded from a
; 32-bit screen into an old-style grafport to be garbage.
; <8> 1/30/90 DVB NEEDED FOR 6.0.5: Don't walk nonexisting portlists at boot time.
; <7> 1/30/90 KON NEEDED FOR 6.0.5: Dither during flatten in copybits,
; Dither32toBitmap and Dither16toBitMap added (stretch.a tables),
; altered modecase selection (comefrom in setup stretch), clear
; dither bit when recording an old picture.
; <6> 1/29/90 KON NEEDED FOR 6.0.5: Added index to index dithering, destination
; clip in stretch, patched out DitherCore8 and 32 to indexed
; dither by moving jmp tables to ram, added quickerdraw patches.
; <5> 1/23/90 KON NEEDED FOR 6.0.5: Added patches for InitGDevice, InitPort,
; BitsToPix (to support devices with changing base addresses), and
; OffscreenVersion.
; <4> 1/22/90 KON NEEDED FOR 6.0.5: Added patches for MakeITable, fixed pixPat
; expansion bug by patching PatConvert, patched GetCIcon so Icon
; size is calculated correctly, added selectors 22 and 23 to
; QDExtDispatcher.
; <3> 1/18/90 KON NEEDED FOR 6.0.5: Added DrawPicture, PicItem1, and StdOpCode
; patches. Fixed bug in StdOpCode so it handles header version -2
; correctly.
; <2> 1/16/90 KON NEEDED FOR 6.0.5: Fixed various picture patch bugs.
; <1> 1/16/90 KON NEEDED FOR 6.0.5: Checked in for the first time.
;
; To Do:
;
;--------------------------------------------------------------------------------
;
; Things that have been fixed on the Mac II, but will not be fixed on the ci:
;
; Arithmetic loops work when vertically aligned, horizontally overlapped on
; MacII, but will not be added to ci since it requires patching out the entire
; blit loop for a case that will probably never happen.
;
;--------------------------------------------------------------------------------
;
MACHINE MC68020 ; changed from MC68000 to MC68020 <24July89smb>
IF (&TYPE('SCRIPT_CHAR_EXTRA') = 'UNDEFINED') THEN
IF forROM THEN
SCRIPT_CHAR_EXTRA EQU 0
ELSE
SCRIPT_CHAR_EXTRA EQU 1
ENDIF
ENDIF
IF (&TYPE('hasGlyphState') = 'UNDEFINED') THEN
IF forROM THEN
hasGlyphState EQU 0
ELSE
hasGlyphState EQU 1
ENDIF
ENDIF
WholeErrors EQU 1
INCLUDE 'SysErr.a'
INCLUDE 'FastTraps.a'
INCLUDE 'PatchMacros.a'
INCLUDE 'paletteEqu.a' ;
INCLUDE 'palettePriv.a'
include 'quickEqu.a' ;
include 'colorequ.a'
INCLUDE 'qdHooks.a'
INCLUDE 'SysEqu.a'
INCLUDE 'VideoEqu.a'
include 'HardwarePrivateEqu.a'
INCLUDE 'fontPrivate.a'
INCLUDE 'ToolEqu.a'
GBLC &CurFile ;current file name used by DrawingVars
MACRO
_tstMFExists
move.l ($E00+$9f*4),d0 ;get address of unimplemented trap
cmp.l ($E00+$8f*4),d0 ;same as OSDispatch?
ENDM
START PROC EXPORT
IMPORT InitPatches
EXPORT StartPatch
RomVersions Aurora
StartPatch
; Bra InitPatches ; Carry out the patches
jmpFar InitPatches,a0 ;do the patches
DC.B 'ptch' ; resource type
DC.B 'QDci' ; patch ID.
ENDPROC
;
; Rom entry points used by several of the picture routines.
;
PutPicData EQU $32BD0
DPutPicOp EQU $32C90
PutPicOp EQU $32C96
DPutPicByte EQU $32BF0
PutPicByte EQU $32BF6
PutPicWord EQU $32C10
PutPicLong EQU $32C30
PutPicTable EQU $32FC0
PutPicRgn EQU $32CD0
PutPMData EQU $336D0
;=========================================================================================
;=========================================================================================
;= =
;= RESIDENT PATCH INSTALL CODE IS BELOW THIS POINT =
;= =
;=========================================================================================
;=========================================================================================
;
; Add routines to calculate to reduce numer and denom by GCD
;
; These are called by DrawPicture and PicItem1
;
CalcGCD PROC EXPORT
; Routine returns GCD( d0, d1 ) using Euclidean method
; On Entry: D0 and D1 contain word size values to reduce
; On Exit: D0 and D1 both contain GCD
;
cmp.l d0,d1 ;while d0 != d1 (unsigned word compare)
beq.s @FoundGCD
bgt.s @D1isBigger ; if( d1 < d0 )
exg d0,d1 ; swap( d1, d0 )
@D1isBigger
sub d0,d1 ; d1 = d1 - d0
bra.s CalcGCD ;end while
@FoundGCD
rts ;d0 and d1 contain GCD
ENDPROC
;
; <124> Bring back SeedFill and CalcMask patches until the future is here.
;
if not(TheFuture) then ; <124>
;=========================================================================================
;=========================================================================================
;
; Patch SeedFill and CalcMask to check both up and down on the first pass of filling
;
;=========================================================================================
;=========================================================================================
SeedFill PROC EXPORT
EXPORT CalcMask
ciSeedFill EQU $35A4C
ciGoHome EQU $35B0A
;-------------------------------------------------------------------------
;
; PROCEDURE SeedFill(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER;
; seedH,seedV: INTEGER)
;
MOVE.L (SP)+,A0 ;pop return addr
MOVEQ #-1,D0 ;get a long of -1
MOVE.L D0,-(SP) ;push edge = all ones
BRA.S SHARE ;share common code
;-------------------------------------------------------------------------
;
; PROCEDURE CalcMask(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER);
;
CalcMask MOVE.L (SP)+,A0 ;pop return addr
MOVEQ #-1,D0 ;get a long of -1
MOVE.L D0,-(SP) ;push seed = (-1,-1)
CLR.L -(SP) ;push edge = zeros
SHARE MOVE.L A0,-(SP) ;restore return addr
;-------------------------------------------------------------------------
;
; LOCAL PROCEDURE MakeMask(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER;
; seedH,seedV: INTEGER;
; edge: LongInt);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE EQU 24
srcPtr EQU PARAMSIZE+8-4 ;long
dstPtr EQU srcPtr-4 ;long
srcRow EQU dstPtr-2 ;word
dstRow EQU srcRow-2 ;word
height EQU dstRow-2 ;word
words EQU height-2 ;word
seedH EQU words-2 ;word
seedV EQU seedH-2 ;word
edge EQU seedV-4 ;long
dstBump EQU -2 ;word
saveStk EQU dstBump-4 ;long
varSize EQU saveStk ;total locals
LINK A6,#varSize ;allocate stack frame
MOVEM.L D3-D7/A2-A4,-(SP) ;save regs
MOVE.L SP,saveStk(A6) ;save stack pointer
;
; prepare height and words for DBRA count. Quit if either <= 0.
;
MOVE words(A6),D5 ;get count of words
BLE GOHOME ;quit if words <= 0
SUB #1,D5 ;subtract 1 for DBRA count
SUB #1,height(A6) ;convert height to DBRA
BLT GOHOME ;quit if height <= 0
;
; init dst to all ones:
;
MOVE words(A6),D0 ;get # of words
ADD D0,D0 ;double for bytes
MOVE dstRow(A6),D1 ;get dstRow
SUB D0,D1 ;subtract bytes for dstBump
MOVE D1,dstBump(A6) ;save dstBump for later
MOVE.L dstPtr(A6),A2 ;point to dst
MOVEQ #-1,D0 ;get some black
MOVE height(A6),D3 ;init DBRA rowCount
BLACK1 MOVE D5,D2 ;init DBRA wordCount
BLACK2 MOVE D0,(A2)+ ;put a word of black
DBRA D2,BLACK2 ;loop all words in row
ADD D1,A2 ;bump to next row
DBRA D3,BLACK1 ;loop height rows
;
; clear one dst pixel at seedH,seedV
;
MOVE seedV(A6),D0 ;get seed vert coord
BLT.S NOSEED ;skip if neg (no seed)
MULU dstRow(A6),D0 ;mul times dst row
MOVE.L dstPtr(A6),A0 ;point to dst
ADD.L D0,A0 ;add vertical offset <EHB 28-Oct-85>
MOVE seedH(A6),D0 ;get seed horiz coord
MOVE D0,D1 ;copy seedH
ASR #3,D0 ;div by 8 for byte
NOT D1 ;invert bit number
BCLR D1,0(A0,D0) ;clear seed pixel
NOSEED
;
; allocate a scanline buffer of ones or zeros on the stack:
;
MOVE.L edge(A6),D6 ;get zero or all ones
MOVE D5,D1 ;get longCount
NEXTBUF MOVE D6,-(SP) ;write a word of ones or zeros
DBRA D1,NEXTBUF ;loop all words
MOVE.L srcPtr(A6),A0 ;point to top of src
MOVE.L dstPtr(A6),A2 ;point to top of dst
st d7 ;set dirty flag to force <KON 24JAN91>
; bra.s FirstPass ;search up and down <KON 24JAN91>
;NXTPASS SF D7 ;clear dirty flag
FirstPass
jmpROM ciSeedFill
GoHome
jmpROM ciGoHome
ENDPROC
endif ; <124> of not TheFuture
;=========================================================================================
;=========================================================================================
;
; Patch to set up pattern hilite correctly when slabbing to 16 and 32-bit destinations.
; <08OCT90 SMC> <73>
;
;=========================================================================================
;=========================================================================================
SlabMode PROC EXPORT
&CurFile SETC 'DRAWSLAB'
INCLUDE 'DrawingVars.a'
ciSkipHilite EQU $2FEF2
ciClrInvBit EQU $2FF38
ciPatPrep EQU $2FEFC
AND #$37,D2 ;toss all but arithmetic, hilite bits + variant bits
BCLR #5,D2 ;arithmetic mode?
BEQ.S @clrInvBit ;if so, dont clear the invert bit
BCLR #4,D2 ;hilite?
BEQ.S @skipHilite ;if not, dont add hilite offset
CMP #16,dstPix+pixelSize(A6)
BLT.S @1
jsrROM ciPatPrep
@1: MOVEQ #8,D2 ;hilite is at $20, so put ($20 / 2) - 8 here
@skipHilite
jmpROM ciSkipHilite
@clrInvBit
AND #$3,D2 ;GET LO 2 BITS OF MODE, clearing bit 4 also
BNE.S @4 ;if not a copy mode, skip over this stuff
TST.B alphaMode(A6) ;are drawing in alpha mode?
BEQ.S @4 ;no, use normal loops
LEA slMASK8A,A4 ;get address of small pat alpha copy loop
CMP #4,PATROW(A6) ;large pattern?
BLE.S @3 ;no, exit
LEA slXMASK8A,A4 ;yes, use big pattern copy loop
@3 RTS
@4 jmpROM ciClrInvBit
; CMP #4,PATROW(A6) ;NEED EXPANDED PATTERN?
;ciPatPrep
; MOVE #$1F,patHMask(A6) ;set up patHMask for 1 long for small patterns
; CMP #4,PATROW(A6) ;NEED EXPANDED PATTERN?
; BLE.S @1 ;if not, all ready to go
; MOVEM.L D2/D3,-(SP) ;save work registers...
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 58: (pat as mask) background color <--> hilite color
; <85> fixed slab hiliting with pixpats.
;
; Note that a fast case could be implemented (like in rgnblt, bitblt) if the pattern source
; was known to be black.
ciArithSetup EQU $2F3A0
EXPORT slHilite, RAMslArith16Tab, RAMslArith32Tab
slHilite
MOVEM.L D7/A4-A5,-(SP) ;preserve extra registers
jsrROM ciArithSetup ;set up registers for slab bitblt
BFEXTU transColor(A6){0:D7},D5 ;get a pixel of the background color
BFEXTU hilitColor(A6){0:D7},D0 ;get a pixel of the hilite color
MOVE.L D0,A0 ;save the hilite color pixel in a free register
TST D2 ;TEST NUMBER OF BYTES TO DO
BRA.S @loopEnd
@loopRight
AND.L D1,D3 ;combine left and right masks
@loopTop
ADD.L D7,D6 ;advance the pattern
AND patHMask(A6),D6 ;constrict it to the width of the pattern
BFEXTU D3{D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A2){D4:D7},D0 ;a pixel of the clip region
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the pattern
CMP.L D5,D0 ; <85>
BEQ.S @skip
BFEXTU (A1){D4:D7},D0 ;get a pixel of the destination
CMP.L D5,D0 ;same as the background color?
BNE.S @tryNew
MOVE.L A0,D0 ;put hilite color in data register
BFINS D0,(A1){D4:D7} ;move hilite color to destination
BRA.S @skip
@tryNew
CMP.L A0,D0 ;same as new color?
BNE.S @skip
BFINS D5,(A1){D4:D7} ;move to the destination
@skip
ADD.L D7,D4 ;bump destination and mask
MOVE D4,D0 ;copy destination offset
AND #31,D0 ;combine with long sized mask
BNE.S @loopTop ;loop if havent finished a long yet
MOVEQ #-1,D3 ;flush the mask
SUBQ #1,D2 ;decrement long counter
@loopEnd
BGT.S @loopTop ;do it for all of the pixels on the line (or within the mask)
BEQ.S @loopRight
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
RTS
slAvg16 EQU $0
slAddPin16 EQU $0
slAddOver16 EQU $0
slSubPin16 EQU $0
slTransparent16 EQU $0
slMax16 EQU $0
slSubOver16 EQU $0
slMin16 EQU $0
slAvg32 EQU $0
slAddPin32 EQU $0
slAddOver32 EQU $0
slSubPin32 EQU $0
slTransparent32 EQU $0
slMax32 EQU $0
slSubOver32 EQU $0
slMin32 EQU $0
RAMslArith16Tab
slArith16Tab
DC.L slAvg16-slArith16Tab ;10 AVG(PAT, DST, WEIGHT) --> DST
DC.L slAddPin16-slArith16Tab ;12 PAT + DST --> DST (pin to max)
DC.L slAddOver16-slArith16Tab ;13 PAT + DST --> DST (no pin)
DC.L slSubPin16-slArith16Tab ;16 DST - PAT --> DST (pin to min)
DC.L slTransparent16-slArith16Tab ;18 PAT less bg --> DST
DC.L slMax16-slArith16Tab ;1A MAX(PAT, DST) --> DST
DC.L slSubOver16-slArith16Tab ;1C DST - PAT --> DST (no pin)
DC.L slMin16-slArith16Tab ;1E MIN(PAT, DST) --> DST
DC.L slHilite-slArith16Tab ;20 (pat as mask) hilite <--> background
RAMslArith32Tab
slArith32Tab
DC.L slAvg32-slArith32Tab ;10 AVG(PAT, DST, WEIGHT) --> DST
DC.L slAddPin32-slArith32Tab ;12 PAT + DST --> DST (pin to max)
DC.L slAddOver32-slArith32Tab ;13 PAT + DST --> DST (no pin)
DC.L slSubPin32-slArith32Tab ;16 DST - PAT --> DST (pin to min)
DC.L slTransparent32-slArith32Tab ;18 PAT less bg --> DST
DC.L slMax32-slArith32Tab ;1A MAX(PAT, DST) --> DST
DC.L slSubOver32-slArith32Tab ;1C DST - PAT --> DST (no pin)
DC.L slMin32-slArith32Tab ;1E MIN(PAT, DST) --> DST
DC.L slHilite-slArith32Tab ;20 (pat as mask) hilite <--> background
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST
;
; Slab small pattern copy using alpha mask
;
slMASK8A
MOVE.L alphaMask(A6),D0 ;get alpha mask
AND.L D0,D1 ;clip left mask with alpha mask
AND.L D0,D3 ;clip right mask with alpha mask
MOVE.L D0,A0 ;save copy of alpha mask
TST D2 ;re-test long count
BRA.S DO8A
END8A AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
NEXT8A MOVE.L D6,D0 ;GET PATTERN DATA
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
AND.L D3,D0 ;MASK PATTERN DATA
NOT.L D3 ;MAKE NOTMASK
AND.L (A1),D3 ;AND NOTMASK WITH OLD DST
OR.L D0,D3 ;FILL HOLE WITH PATTERN
MOVE.L D3,(A1)+ ;UPDATE DST
MOVE.L A0,D3 ;FLUSH MASK to alpha mask
SUB #1,D2 ;DEC LONG COUNT
DO8A BGT NEXT8A ;LOOP FOR ALL LONGS IN ROW
BEQ END8A ;DO LAST LONG WITH MASK
RTS
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 8 OR 12: BIG PATTERN --> DST
;
; Slab big pattern copy using alpha mask
;
slXMASK8A
MOVE D7,-(SP) ;SAVE WORK REGISTER
MOVE PATHMASK(A6),D7 ;GET HORIZ MASK
MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
AND D7,D6 ;MASK INDEX INTO PATTERN
MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
ADD.L PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN
MOVE.L alphaMask(A6),D0 ;get alpha mask
AND.L D0,D1 ;clip left mask with alpha mask
AND.L D0,D3 ;clip right mask with alpha mask
MOVE.L D0,A0 ;save copy of alpha mask
TST D2 ;re-test long count
BRA.S XDO8A
XEND8A AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
XNEXT8A MOVE.L 0(A3,D6),D0 ;GET PATTERN DATA
ADDQ #4,D6 ;BUMP PATTERN INDEX
AND D7,D6 ;MASK INDEX INTO PATTERN
AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
AND.L D3,D0 ;MASK PATTERN DATA
NOT.L D3 ;MAKE NOTMASK
AND.L (A1),D3 ;AND NOTMASK WITH OLD DST
OR.L D0,D3 ;FILL HOLE WITH PATTERN
MOVE.L D3,(A1)+ ;UPDATE DST
MOVE.L A0,D3 ;FLUSH MASK to alpha mask
SUB #1,D2 ;DEC LONG COUNT
XDO8A BGT XNEXT8A ;LOOP FOR ALL LONGS IN ROW
BEQ XEND8A ;DO LAST LONG WITH MASK
MOVE (SP)+,D7 ;RESTORE WORK REGISTER
RTS
EXPORT RAMFastSlabMode
;--------------------------------------------------------------------
;
; PROCEDURE FastSlabMode, Call when rect clipped and pattern black.
;
; INPUT: D2: MODE, CLOBBERED mode 0=black, 1=xor, 2=white
; OUTPUT: A4: MODECASE
;
ciFASTTAB EQU $30050
;NOTE: FAST8A,10A and 11A must be before FASTTAB so that offsets are positive
ALIGN Alignment
; FAST FOREGROUND/BACKGROUND SLAB USING ALPHA MASK:
FAST11A MOVE.L D5,D4 ;USE BKCOLOR INSTEAD OF FGCOLOR
FAST8A MOVE.L alphaMask(A6),D0 ;GET ALPHA MASK
AND.L D0,D1 ;CLIP LEFTMASK WITH ALPHAMASK
AND.L D0,D3 ;CLIP RIGHTMASK WITH ALPHAMASK
MOVE.L D0,A0 ;save copy of alpha mask
TST D2 ;RETEST THE LONG COUNT
BEQ.S MERGE8A ;BR IF ALL IN ONE LONG
MOVE.L D3,D0 ;GET LEFTMASK
NOT.L D0 ;GET NOT LEFTMASK
AND.L (A1),D0 ;PUNCH OUT DST
AND.L D4,D3 ;OR FGCOLOR INTO LEFTMASK
OR.L D3,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;AND PUT TO DST
SUB #2,D2 ;ADJUST LONGCOUNT FOR DBRA
BLT.S LAST8A ;BR IF NO UNMASKED LONGS
MOVE.L A0,D3 ;GET CENTER MASK
NOT.L D3 ;GET NOT OF MASK
LOOP8A MOVE.L (A1),D0 ;GET THE DST
EOR.L D4,D0 ;APPLY FGCOLOR
AND.L D3,D0 ;MASK OUT PART OF DST
EOR.L D4,D0 ;REAPPLY FGCOLOR
MOVE.L D0,(A1)+ ;AND PUT TO DST
DBRA D2,LOOP8A ;LOOP ALL UNMASKED LONGS
BRA.S LAST8A ;GO DO LAST LONG
MERGE8A AND.L D3,D1 ;COMBINE LEFTMASK AND RIGHTMASK
LAST8A MOVE.L D1,D0 ;GET RIGHTMASK
NOT.L D0 ;GET NOT RIGHTMASK
AND.L (A1),D0 ;PUNCH OUT DST
AND.L D4,D1 ;OR FGCOLOR INTO RIGHTMASK
OR.L D1,D0 ;COMBINE SRC AND DST
MOVE.L D0,(A1)+ ;AND PUT TO DST
RTS ;AND RETURN
ALIGN Alignment
; FAST XOR SLAB USING ALPHA MASK:
FAST10A MOVE.L alphaMask(A6),D0 ;GET ALPHAMASK
AND.L D0,D1 ;CLIP LEFTMASK WITH ALPHAMASK
AND.L D0,D3 ;CLIP RIGHTMASK WITH ALPHAMASK
TST D2 ;RETEST THE LONG COUNT
BEQ.S MERGE10A ;BR IF ALL IN ONE LONG
EOR.L D3,(A1)+ ;XOR LEFTMASK INTO DST
SUB #2,D2 ;ADJUST LONGCOUNT FOR DBRA
BLT.S LAST10A ;BR IF NO UNMASKED LONGS
LOOP10A EOR.L D0,(A1)+ ;INVERT A LONG OF DST
DBRA D2,LOOP10A ;LOOP ALL UNMASKED LONGS
LAST10A EOR.L D1,(A1)+ ;XOR RIGHTMASK INTO DST
RTS ;AND RETURN
MERGE10A AND.L D3,D1 ;COMBINE LEFTMASK AND RIGHTMASK
EOR.L D1,(A1)+ ;XOR RIGHTMASK INTO DST
RTS ;AND RETURN
RAMFastSlabMode
leaROM ciFASTTAB,A4
AND #$3,D2 ;GET LO 2 BITS OF MODE
TST.B alphaMode(A6) ;are we drawing in alpha mode?
BEQ.S @1 ;no, use original fast cases
LEA FASTTAB,A4 ;POINT TO MODE TABLE
@1 MOVE.B 0(A4,D2),D2 ;GET OFFSET FROM FASTTAB
SUB D2,A4 ;GET CASE JUMP ADDRESS
RTS
FASTTAB DC.B FASTTAB-FAST8A ;alpha BLACK (foreground)
DC.B FASTTAB-FAST10A ;alpha XOR
DC.B FASTTAB-FAST11A ;alpha WHITE (background)
DC.B 0 ;alignment
;=========================================================================================
;=========================================================================================
;
; Patch to fix transparent rgnblt. Removes optimization that was losing pattern data.
; <08Oct90 SMC> <72>
;
;=========================================================================================
;=========================================================================================
rTransparent PROC EXPORT
IMPORT rTransparent8
ciNxtNewSrc EQU $2ABAC
&CurFile SETC 'RGNBLT'
INCLUDE 'DrawingVars.a'
TST.L D3 ;right to left?
BMI.S @1 ;if so, skip
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
BEQ rTransparent8 ;yes, go use quickdraw
@1: LEA @RealrTransparent,A0
MOVE.L A0,ModeCase(A6)
@RealrTransparent
MOVE patHMask(A6),D1 ;set up source constriction
MOVE pixInLong1(A6),A0 ;set up absolute long bump
MOVE longBump(A6),A2 ;set up long bump
BFEXTU D5{0:D7},D0
MOVE.L D0,A1 ;set up pixel of background
@loopTop
AND D1,D6 ;constrict to the source long if in a pattern mode
BFEXTU (A4){D4:D7},D0 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A3){D6:D7},D0 ;get a pixel of the source (zeros top word)
CMP.L D0,A1 ;same as a pixel of the background?
BEQ.S @skip
BFINS D0,(A5){D4:D7} ;move to the destination
@skip
ADD.L D3,D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel
ADD.L D3,D4 ;bump destination and mask
DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask)
jmpROM ciNxtNewSrc
;=========================================================================================
;=========================================================================================
;
; Patch to fix right edge problem in bSubOver16. The right pixel was getting moved
; from the source using a move.l instead of a move.w. As a result, the pixel one to
; the right of the last source pixel was being used.
; Table from BitBlt.a moved to RAM.
; <SMC 08Oct90> <71>
;
;=========================================================================================
;=========================================================================================
RAMbArith16Tab PROC EXPORT
bAvg16 EQU $0
bAddPin16 EQU $0
bAddOver16 EQU $0
bSubPin16 EQU $0
bTransparent16 EQU $0
bMax16 EQU $0
;bSubOver16 EQU $0 ;This routine added below
bMin16 EQU $0
bAvg16Half EQU $0
bArith16Tab
DC.L bAvg16-bArith16Tab ;18 AVG(SRC, DST, WEIGHT) --> DST
DC.L bAddPin16-bArith16Tab ;1A SRC + DST --> DST (pin to max)
DC.L bAddOver16-bArith16Tab ;1C SRC + DST --> DST (no pin)
DC.L bSubPin16-bArith16Tab ;1E DST - SRC --> DST (pin to min)
DC.L bTransparent16-bArith16Tab ;20 SRC less bg --> DST
DC.L bMax16-bArith16Tab ;22 MAX(SRC, DST) --> DST
DC.L bSubOver16-bArith16Tab ;24 DST - SRC --> DST (no pin)
DC.L bMin16-bArith16Tab ;26 MIN(SRC, DST) --> DST
DC.L bAvg16Half-bArith16Tab ;50% case
&CurFile SETC 'BITBLT'
INCLUDE 'DrawingVars.a'
ciNxtNewSrc32 EQU $2CC78
bSubOver16
move.l a4,a0 ;get working copy of srcptr
add.w d6,a0 ;index into pattern
move.l a5,a2 ;get working copy of dstptr
move.w #$3def,d0 ;get high bit clearing mask
move.w #$4210,d1 ;get high bit mask
@loopTop
move.w d1,d3 ;copy high bit mask
move.w (a0),d7 ;get a pixel of the source xrgb
add.w a3,a0 ;bump bidirectionally
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 (a2),d5 ;get a pixel of the dest xrgb <SMC 08OCT90> <71>
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,(a2) ;move to the destination
add.w a3,a2 ;bump bidirectionally
addq.l #2,d6 ;bump pattern offset
and.w patHMask(a6),d6 ;constrict to the source long if in a pattern mode
bne.s @patOK ;don't need to reload pat ptr
move.l a4,a0 ;reload pat ptr
@patOK DBRA D2,@loopTop ;do it for all pixels on the line
jmpROM ciNxtNewSrc32 ;LOOP BACK FOR MORE
;=========================================================================================
;=========================================================================================
;
; Patch to fix transparent bitblt. Removes an optimization that was losing pattern
; data. It also fixes transparent copies between overlapping sources and destinations.
; <08Oct90 SMC> <72>
;
;=========================================================================================
;=========================================================================================
EXPORT bTransparent
IMPORT bTransparent8
ciNxtNewSrc EQU $2CC8A
bTransparent
;
; if we are going backwards, align destination and mask <14AUG90 KON>
;
lea @RealbTransparent1,a1 ; <08Oct90 SMC> <72>
tst.l (sp) ;is bump amount negative? <14AUG90 KON>
bmi.s @1 ; <14AUG90 KON>
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode? <08Oct90 SMC> <72>
BEQ bTransparent8 ; <08Oct90 SMC> <72>
BRA.S @RealbTransparent1 ; <08Oct90 SMC> <72>
@1: sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON>
lea @RealbTransparent,a1 ;remember correct entry point for remaining scans <14AUG90 KON>
@RealbTransparent
sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON>
@RealbTransparent1
cmp.w #32,d7 ;1 pixel per long? <08Jan89 BAL>
beq.s @firstMask ;yes, d2 is unfortunately zero <08Jan89 BAL>
TST D2 ;is there only 1 long?
BGT.S @firstMask ;if not, use the first mask in D1
@forceLast
OR.B #3,doneMid(A6) ;note that the first part and mid part are done
@lastMask
MOVE pixInLong(A6),D2 ;loop once for each pixel in the long
AND.L lastMask(A6),D1 ;MASK:=MASK AND LASTMASK
@firstMask
@loopTop
AND patHMask(A6),D6 ;constrict to the source long if in a pattern mode
BFEXTU D1{D0:D7},D3 ;a pixel of the mask
BEQ.S @skip
BFEXTU (A4){D6:D7},D3 ;get a pixel of the source (zeros top word)
CMP.L D3,A3 ;same as a pixel of the background?
BEQ.S @skip
BFINS D3,(A5){D0:D7} ;move to the destination
@skip
ADD.L (SP),D6 ;BUMP SRCPTR LEFT OR RIGHT by 1 pixel
ADD.L (SP),D0 ;bump destination and mask
DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask)
@loopEnd
ADDQ #1,D2 ;check to see if we ended on a natural long
BEQ.S @noPixelAlign ;if so, expect a -1 here
SUB.L (SP),D6 ;unbump source
SUB.L (SP),D0 ;unbump destination
BRA.S @loopEnd
@noPixelAlign
MOVEQ #-1,D1 ;flush mask
BSET #0,doneMid(A6) ;has the middle part already been done?
BNE.S @midDone ;if so, skip it
MOVE midCount(A6),D2 ;reset to mid count
BMI.S @forceLast ;if none, just do the last part
BRA.S @loopTop
@midDone
BSET #1,doneMid(A6) ;already done the last mask part too?
BEQ.S @lastMask ;if not, do it
jmpROM ciNxtNewSrc
EXPORT bXMAIN8,bSETUP8,bLONG8,bXLONG8
cibXMAIN8 EQU $2D1B0
cibSETUP8 EQU $2CFC0
cibLONG8 EQU $2CF30
cibXLONG8 EQU $2D150
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES)
; PATTERN ALREADY HAS COLOR IN IT, SO NONE IS ADDED
;
bXMAIN8 TST.B alphaMode(A6) ;drawing in alpha mode? ;Start of alpha changes block
BEQ.S @bXMAIN8G ;no, use normal loop
MOVE.L alphaMask(A6),D3 ;get alpha mask
AND.L D3,D1 ;AND ALPHA WITH LEFT MASK
MOVE.L D1,FIRSTMASK(A6) ;SAVE THAT RESULT
AND.L D3,D5 ;AND ALPHA WITH RIGHT MASK
BRA.S @bX8 ;jump into alpha loop
@bXMAIN8G jmpROM cibXMAIN8
ALIGN Alignment
@bXEND8 AND.L D5,D1 ;MASK:=MASK AND LASTMASK
@bX8 MOVE.L 0(A4,D6),D4 ;GET PATTERN
ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
MOVE.L (A5),D0 ;GET DST
EOR.L D0,D4 ;APPLY DST TO PATTERN
AND.L D1,D4 ;MASK OFF EDGE
EOR.L D0,D4 ;REAPPLY DST
MOVE.L D4,(A5)+ ;PUT RESULT TO DST
MOVE.L D3,D1 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
BEQ @bXEND8 ;DO LAST LONG WITH LASTMASK
BLT.S @nxtBigPat ;BUMP TO NEXT PATTERN ROW
SUBQ #1,D2 ;DEC LONG COUNT
NOT.L D3 ;REVERSE ALPHA MASK
@alpha MOVE.L 0(A4,D6),D4 ;GET PATTERN
ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
MOVE.L (A5),D0 ;GET DST
EOR.L D4,D0 ;APPLY PATTERN TO DST
AND.L D3,D0 ;MASK WITH ALPHA MASK
EOR.L D4,D0 ;REAPPLY PATTERN
MOVE.L D0,(A5)+ ;PUT RESULT TO DST
DBRA D2,@alpha ;DEC LONG COUNT
NOT.L D3 ;REVERSE ALPHA MASK BACK
BRA.S @bXEND8 ;DO LAST LONG WITH LASTMASK
@nxtBigPat clr.w d6 ;make it unsigned
SWAP D6 ;GET VERT POSITION IN PAT
SUB.l D6,A4 ;GET BACK PAT BASE
ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN
AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN
ADD.l D6,A4 ;BUMP TO PROPER VERT
SWAP D6 ;SAVE VERTICAL POSITION
MOVE PATHPOS(A6),D6 ;INIT HORIZONTAL OFFSET
ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW
SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT
beq GOHOME ;LOOP FOR ALL SRCROWS
MOVE.L FIRSTMASK(A6),D1 ;MASK:=FIRSTMASK
MOVE LONGCNT(A6),D2 ;GET LONGCOUNT
bra.s @bX8 ;go do next row
;end of alpha changes block
;------------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES)
;
bSETUP8 TST.B alphaMode(A6) ;drawing in alpha mode?
BEQ.S @bSETUP8 ;no, use normal loop
MOVE.L alphaMask(A6),D3 ;get alpha mask
AND.L D3,D1 ;AND ALPHA WITH LEFT MASK
MOVE.L D1,FIRSTMASK(A6) ;SAVE THAT RESULT
AND.L D3,D5 ;AND ALPHA WITH RIGHT MASK
BRA.S @bMAIN8 ;jump into alpha loop
@bEND8 AND.L D5,D1 ;MASK:=MASK AND LASTMASK
@bMAIN8 MOVE.L D1,D0 ;COPY MASK
AND.L D6,D1 ;GET MASKED PATTERN
NOT.L D0 ;REVERSE MASK
AND.L (A5),D0 ;GET NOT MASKED DST
OR.L D1,D0 ;COMBINE PATTERN AND DST
MOVE.L D0,(A5)+ ;PUT RESULT TO DST
MOVE.L D3,D1 ;FLUSH MASK
SUB #1,D2 ;DEC LONG COUNT
BGT @bMAIN8 ;LOOP TILL LAST LONG
BEQ @bEND8 ;DO LAST LONG WITH LASTMASK
@NXTPAT ADD #1,D7 ;BUMP PATTERN SELECTOR
AND #$0F,D7 ;MOD 16 FOR 16 LONG REPEAT
MOVE.L ([EXPAT,A6],D7*4),D6 ;GET FIRST PATTERN DATA
ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW
SUBQ #1,HEIGHT(A6) ;DECREMENT ROWCOUNT
BEQ.S GOHOME ;LOOP FOR ALL SRCROWS
MOVE.L FIRSTMASK(A6),D1 ;MASK:=FIRSTMASK
MOVE LONGCNT(A6),D2 ;GET LONGCOUNT
BRA.S @bMAIN8 ;GO NEXT LINE
@bSETUP8 jmpROM cibSETUP8
GOHOME RTS
;-----------------------------------------------------------
;
; OPTIMIZE MODE 8 OR 12 IF DST FITS IN ONE LONG (VERT LINES ETC)
;
bLONG8 AND.L alphaMask(A6),D1
jmpROM cibLONG8
;-----------------------------------------------------------
;
; OPTIMIZE MODE 8 OR 12 IF DST FITS IN ONE LONG (VERT LINES ETC)
;
bXLONG8 AND.L alphaMask(A6),D1
jmpROM cibXLONG8
;=========================================================================================
;=========================================================================================
;
; Patch to handle vertically aligned hilites (like that ever happens) and to
; preserve a non-white background color through the entire blit (more common).
; <14SEP90 SMC>
;
;=========================================================================================
;=========================================================================================
bSloHilite PROC EXPORT
ciRealbSloHilite1 EQU $2DE14
;
; if we are going backwards, align destination and mask <14AUG90 KON>
;
leaROM ciRealbSloHilite1,a1 ; <13SEP90 SMC>
BFEXTU D4{0:D7},D4 ;set up pixel of the background color <13SEP90 SMC>
tst (sp) ;is bump amount negative? <14AUG90 KON>
bpl.s @RealbSloHilite1 ; <14AUG90 KON>
sub.l (SP),D6 ;bump src right OR left by 1 pixel first time only <14AUG90 KON>
lea @RealbSloHilite,a1 ;remember correct entry point for remaining scans <14AUG90 KON>
@RealbSloHilite
; tst (sp) ;is bump amount negative? <08OCT90 SMC>
; bpl.s @RealbSloHilite1 ; <08OCT90 SMC>
sub.l (SP),D0 ;align destination and mask each scan line <14AUG90 KON>
@RealbSloHilite1
jmpROM ciRealbSloHilite1
;=========================================================================================
;
; Patch to MapRgn to return immediatly if the region is rectangular and wide open
; <7Sept90 KON>
;
;=========================================================================================
;=========================================================================================
newMapRgn PROC EXPORT
;-------------------------------------------------------------
;
; PROCEDURE MapRgn(rgn: RgnHandle; fromRect,toRect: Rect);
;
; A6 OFFSETS OF PARAMETERS AND LOCALS AFTER LINK:
;
rts EQU 0
toRect EQU rts+4
fromRect EQU toRect+4
rgn EQU fromRect+4
NOTSAME MOVE.L rgn(sp),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE RGN
CMP #10,RGNSIZE(A0) ;IS RGN RECTANGULAR ?
BNE.S BackToROM ;Back to ROM version
;
; Don't do anything if region is rectangular and wide open since MapRect will choke <7Sept90 KON>
; a0 points to rgn
;
cmp.l #$80018001,2(a0) ;
bne.s BackToROM
cmp.l #$7fff7fff,6(a0) ;wide open?
bne.s BackToROM ;No, Use ROM routine
;
; region is rectangular and wide open, return without doing anything
;
move.l (sp)+,a0 ;get return address
add.l #12,sp ;remove toRect, fromRect, and rgn
jmp (a0) ;return to caller
BackToROM
BackToTrap OldMapRgn
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to RgnBlt so patterned hilite works.
;
;=========================================================================================
;=========================================================================================
RgnBlt PROC EXPORT
EXPORT rslowHilite
EXPORT rXMASK8, rMASK8
ciOldWay EQU $2A73C
ciNewWay EQU $2A73E
ciNoHilite EQU $2A726
ciNxtNewSrc EQU $2ABAC
;--------------------------------------------------------------
;
; PROCEDURE RgnBlt(srcPix,dstPix: PixMap;
; srcRect,dstRect: Rect;
; mode: INTEGER; pat: Pattern;
; rgnA,rgnB,rgnC: RgnHandle);
;
; See description in RgnBlt.a
;
;----------------------------------------------------
;
; 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 non black/white colors
;----------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
; STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile SETC 'RGNBLT'
INCLUDE 'DrawingVars.a'
;-----------------------------------
;
; SAVE STACK FOR NOW, BECAUSE WE'RE STILL ALLOCATING SCANLINE BUFFERS
;
MOVE.L SP,SAVESTK2(A6) ;PRESERVE STACK POINTER
;-----------------------------------
;
; CALC BUFLEFT AND BUFSIZE (BUFSIZE = DSTSIZE)
;
MOVE MINRECT+LEFT(A6),D1 ;GET MINRECT LEFT
SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL COORDS
EXT.L D1 ;CLEAR HI WORD
LSL.L D4,D1 ;CONVERT PIXELS TO BITS
AND #$FFE0,D1 ;TRUNC TO MULT OF 32
LSR.L D4,D1 ;CONVERT BITS TO PIXELS
ADD BOUNDS+LEFT(A5),D1 ;CONVERT BACK TO LOCAL
MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
SUB D1,D0 ;CALC WIDTH IN DOTS (=SCANSIZE)
move d0,d1 ;save for expansion scanline buffer <C954>
ext.l d1 ;clear out high word <C954>
lsl.l d4,d1 ;convert to bits <C954>
subq.l #1,d1 ;force downward round <C954>
LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 <C954>
MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 <C954>
LSR #5,D0 ;get (pixels in scanbuf)/32 <C954>
ADDQ #1,D0 ;MAKE IT ONE BASED
LSL D4,D0 ;MULTIPLY BY DEPTH
; SUBQ #1,D0 ;MAKE SIZE 0 BASED
addQ #4,D0 ;add in slop for 4-bit <BAL solo>
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK.
;
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-D4
;
MOVEQ #-1,D0 ;assume run clipping <85> start
MOVE LOCMODE(A6),D2 ;GET TRANSFER MODE
CMP #32,D2 ;new arithmetic mode?
BLO @newWay
CMP #64,D2
BHS Done ;unimplemented mode
CMP #48,D2
BLT.S @noHilite
CMP #50,D2 ;source highlight mode?
BEQ.S @oldWay ;if so, can't be fast pattern case
CMP #58,D2 ;pattern highlight mode?
BNE Done ;if not, it is unimplemented
TST PATROW(A6) ;BIG PATTERN?
BNE.S @oldWay ;if so, assume pattern contains background color
MOVE.L exPat(A6),A0 ;check if non-background pattern
MOVE.L BCOLOR(A6),D1 ;get background color
MOVEQ #$0F,D0 ;number of longs in a short pattern
@nextPatRow
CMP.L (A0)+,D1 ;is the row non-background?
DBEQ D0,@nextPatRow ;if so, check for more rows
BEQ.S @oldWay ;if not, cant do fast hiliting
MOVE #$10,locMode(A6) ;set the mode to the fast hilite variety
BRA.S @newWay ;assume D0 = -1
@noHilite
CMP.W #4,d4 ;is dst 16 or 32 bits/pixel?
BGE.S @newWay ;yes, handle new way
CMP.W #32,D2 ;is it an arithmetic mode?
BLT.S @newWay ;no, handle new way
CMP.W #47,D2 ;is it an arithmetic mode?
BGT.S @newWay ;no, handle new way (hilite mode)
@oldWay MOVEQ #0,D0 ;don't use run clipping <85> end
@newWay
move.l d0,runBuf(a6) ;set non-zero for run clipping <1.5> BAL
MOVE.L RGNC(A6),-(SP) ;PUSH USER RGNHANDLE
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.W DSTSHIFT(A6),D4 ;RESTORE DSTSHIFT
MOVE.L DSTRECT(A6),A3 ;RESTORE DSTRECT
;----------------------------------------------------------
;
; ASSUME WE WILL BE DRAWING DOWNWARD AND TO RIGHT.
;
MOVE MINRECT+TOP(A6),FIRSTV(A6) ;FIRSTV:=MINRECT TOP
MOVE MINRECT+BOTTOM(A6),LASTV(A6) ;LASTV:=MINRECT BOTTOM
MOVE.L #$00040001,HBUMP(A6) ;HBUMP:=4 BYTES, VBUMP:=1 SCAN
MOVE.L RGNBUFFER(A6),RGNADDR(A6) ;RGNADDR:=RGNBUFFER
;--------------------------------------------------
;
; CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES
; GET INVERTFLAG INTO D7
;
ciFastHilite EQU $2A7BC
ciAfterNoFastHilite EQU $2A7E6
ciDoOldWay EQU $2A838
SETMODE MOVE LOCMODE(A6),D2 ;GET TRANSFER MODE
MOVE D2,D1 ;SAVE MODE
CMP.W #$10,D2 ;fast hilite mode?
BNE.S @notFastHilite
jmpROM ciFastHilite
; MOVE.L rHiliteTabPtr,A0 ;get address of table (from trap table)
; ADD.L -4(a0,D4*4),a0 ;select routine based on destination depth
; MOVE.L A0,ModeCase(A6) ;set up jump
; MOVE dstPix+pixelSize(A6),D7 ;how far to extract to get a pixel worth
; BFEXTU hilitColor(A6){0:D7},D3 ;and a pixel sized highlight color
; BFEXTU transColor(A6){0:D7},D6 ;set up a pixel sized background color
; CLR patRow(A6) ;no pattern
; BRA GetDst ;go to it
@notFastHilite
CMP.W #$20,D2 ;non-arithmetic mode?
BLO @doOldWay
jmpROM ciAfterNoFastHilite
; AND #$37,D2 ;treat mode MOD $07 + arithmetic bit, hilite bit
; BCLR #4,D2 ;and clear the hilite bit
; BNE.S @Hilite
@doOldWay
jmpROM ciDoOldWay
rslowHilite
CMP #16,D7 ;if 16 or 32 bit/pixel, undo some setup
BLT.S @notDirect
LSL.L #3,D6 ;turn the patOffset back to pixels from bytes
MOVE.L D6,patOffset(A6)
MOVE patHMask(A6),D1 ;convert patHMask back into pixels from bytes
LSL.W #3,D1
MOVE D1,patHMask(A6)
@notDirect
LEA @rsHilite,A0 ;get address of real blit loop
MOVE.L A0,modeCase(A6) ;go there from now on
JMP (A0) ;go there right now
@rsHilite
MOVE patHMask(A6),D1 ;set up source constriction
BFEXTU transColor(A6){0:D7},D0
MOVE.L D0,A1 ;set up pixel of background color
@loopTop
AND D1,D6 ;constrict to the source long if in a pattern mode
BFEXTU (A3){D6:D7},D0 ;get pixel of source
CMP.L A1,D0 ;is it the same as the background color?
BEQ.S @skip ;skip if so
BFEXTU (A4){D4:D7},D0 ;get pixel of the mask
BEQ.S @skip ;skip if empty
BFEXTU (A5){D4:D7},D0 ;get a pixel of the dest (zeros top word)
CMP.L A1,D0 ;same as a pixel of the background?
BEQ.S @putHilite ;yes, go put hilite there
CMP.L D5,D0 ;same as a pixel of the hilite color?
BNE.S @skip ;no, skip it
MOVE.L A1,D0
BFINS D0,(A5){D4:D7} ;yes, move pixel of back color to dest
BRA.S @skip
@putHilite
BFINS D5,(A5){D4:D7} ;move hilite color to dest
@skip ADD.L D3,D6 ;bump srcptr left or right by 1 pixel
ADD.L D3,D4 ;bump destination and mask
DBRA D2,@loopTop ;do it for all of the pixels on the line (or within the mask)
; BRA NxtNewSrc ;loop back for more
jmpROM ciNxtNewSrc
;=========================================================================================
;=========================================================================================
;
; MODE 8 OR 12: Big PATTERN --> DST (FILLING AREAS, DRAWING LINES)
;
;=========================================================================================
;=========================================================================================
ciDONE EQU $2ABA6
cinextMask EQU $2AB3C
;Lifted from cqd.a include file
runMaskBit EQU 30 ;bit number for run MASK instruction
rXMASK8 LEA rXMASK8G,A2 ;get address of normal loop ;Start of alpha changes block
TST.B alphaMode(A6) ;drawing in alpha mode?
BEQ.S @1 ;no, use normal loop
LEA rXMASK8A,A2 ;get address of alpha loop
@1: MOVE.L A2,modeCase(A6) ;save proc address
JMP (A2) ;go there now
ALIGN Alignment
@nxtScan
MOVE PATHPOS(A6),D6 ;GET HORIZONTAL POSITION
SWAP D6 ;GET VERT POSITION IN PATTERN
ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN
AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN
;LEAVE PATVPOS IN D6
add.l d2,a5 ;BUMP DST TO NEXT ROW
MOVE vert(A6),D0
ADDQ #1,D0 ;BUMP DOWN A SCAN LINE
CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ?
bge DONE ;YES, BAIL
subq #1,d1
ble.s nextMask
MOVE D0,vert(A6)
@runs move.l a5,a2 ;set up destAddr
move.l a3,a0 ;set up srcAddr
MOVEQ #0,D4 ;clear out high word
MOVE D6,D4 ;get vert pattern offset
ADD.L D4,A0 ;BUMP TO PROPER ROW
SWAP D6 ;AND GET PATHPOS
move.l a4,A1 ;point to run encoded mask buffer
MOVE.L alphaMask(A6),D5
@inst move.l (a1)+,d3 ;pick up next instruction long
bmi.s @nxtScan
add.w d3,a2 ;bump destptr by skip amount
ADD.W D3,D6 ;BUMP PATTERN POS
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
swap d3 ;get mask/blit cnt and check done flag
bclr #runMaskBit-16,d3 ;check and clear mask flag
BEQ.S @blit
@mask MOVE.L 0(A0,D6),D0 ;GET PATTERN DATA
ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
MOVE.L (A2),D4 ;GET DST
EOR.L D4,D0 ;COMBINE DST AND PATTERN
AND.L (A1)+,D0 ;APPLY REGION MASK
AND.L D5,D0 ;APPLY ALPHA MASK
EOR.L D4,D0 ;REAPPLY DST TO PATTERN
MOVE.L D0,(A2)+ ;PUT RESULT TO DST
DBRA D3,@mask ;LOOP ALL LONGS THIS ROW
BRA.s @inst ;LOOP BACK FOR more runs
@blit MOVE.L 0(A0,D6),D0 ;GET PATTERN DATA
ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
MOVE.L (A2),D4 ;GET DST
EOR.L D4,D0 ;COMBINE DST AND PATTERN
AND.L D5,D0 ;APPLY ALPHA MASK
EOR.L D4,D0 ;REAPPLY DST TO PATTERN
MOVE.L D0,(A2)+ ;PUT RESULT TO DST
DBRA D3,@blit ;LOOP ALL LONGS THIS ROW
BRA.S @inst ;LOOP BACK FOR MORE RUNS
rXMASK8A equ @runs ;end of alpha changes block
DONE jmpROM ciDONE
nextMask
jmpROM cinextMask
ALIGN Alignment
@nxtScan
MOVE PATHPOS(A6),D6 ;GET HORIZONTAL POSITION
SWAP D6 ;GET VERT POSITION IN PATTERN
ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN
AND PATVMASK(A6),D6 ;AND MASK WITHIN PATTERN
;LEAVE PATVPOS IN D6
add.l d2,a5 ;BUMP DST TO NEXT ROW
ADDQ #1,D0 ;BUMP DOWN A SCAN LINE
CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ?
bge.s DONE ;YES, BAIL
subq #1,d1
ble.s nextMask
;rXMASK8
@runs move.l a5,a2 ;set up destAddr
move.l a3,a0 ;set up srcAddr
MOVEQ #0,D5 ;clear out high word <SMC 20Aug90>
MOVE D6,D5 ;get vert pattern offset <SMC 20Aug90>
ADD.L D5,A0 ;BUMP TO PROPER ROW <SMC 20Aug90>
SWAP D6 ;AND GET PATHPOS
move.l a4,A1 ;point to run encoded mask buffer
@inst
move.l (a1)+,d3 ;pick up next instruction long
bmi.s @nxtScan
add.w d3,a2 ;bump destptr by skip amount
ADD.W D3,D6 ;BUMP PATTERN POS
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
swap d3 ;get mask/blit cnt and check done flag
bclr #runMaskBit-16,d3 ;check and clear mask flag
beq.s @blit ;no mask, so go fast
@mask MOVE.L 0(A0,D6),D5 ;GET PATTERN DATA
ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
MOVE.L (A1)+,D4 ;GET MASK
AND.L D4,D5 ;MASK PATTERN DATA
NOT.L D4 ;MAKE NOTMASK
AND.L (A2),D4 ;GET DST DATA
OR.L D4,D5 ;MERGE WITH PAT DATA
MOVE.L D5,(A2)+ ;PUT RESULT TO DST
DBRA D3,@mask ;LOOP ALL LONGS THIS ROW
BRA.s @inst ;LOOP BACK FOR more runs
@blit MOVE.L 0(A0,D6),(A2)+ ;write pattern to dest
ADDQ #4,D6 ;BUMP TO NEXT LONG OF PATTERN
AND D7,D6 ;WRAP WHEN PATTERN REPEATS
DBRA D3,@blit ;LOOP ALL LONGS THIS ROW
BRA.s @inst ;LOOP BACK FOR more runs
rXMASK8G EQU @runs
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES)
;
;-------------------------------------------------------
cirMASK8 EQU $2B0EC
rMASK8 leaROM cirMASK8,A2 ;get address of normal routine ;Start of alpha changes block
TST.B alphaMode(A6) ;drawing in alpha mode?
BEQ.S @1 ;no, use normal loop
LEA rMASK8A,A2 ;get address of alpha loop
@1: MOVE.L A2,modeCase(A6) ;save proc address
JMP (A2) ;go there now
ALIGN Alignment
@nxtScan
ADDQ #1,D7 ;BUMP PATTERN SELECTOR
AND #$F,D7 ;MOD 16 FOR 16 LONG REPEAT
MOVE.L (a3,D7*4),D6 ;GET PATTERN FOR NEXT ROW
add.l d2,a5 ;BUMP DST TO NEXT ROW
MOVE vert(A6),D0
ADDQ #1,D0 ;BUMP DOWN A SCAN LINE
CMP lastV(a6),D0 ;ARE WE AT THE LAST SCAN LINE ?
bge.s DONE ;YES, BAIL
subq #1,d1
ble.s nextMask
MOVE D0,vert(A6)
;rMASK8A
@runs move.l a5,a2 ;init tmp dst ptr
move.l a4,a1 ;point to run encoded mask buffer
MOVE.L alphaMask(A6),D5 ;get alpha mask
@inst move.l (a1)+,d3 ;pick up next instruction long
bmi.s @nxtScan ;if high bit set then done with scan
add.w d3,a2 ;bump destptr by skip amount
swap d3 ;get mask/blit cnt and check done flag
bclr #runMaskBit-16,d3 ;check and clear mask flag
beq.s @blit ;no mask, so go fast
@mask MOVE.L D6,D0 ;GET PATTERN DATA
MOVE.L (A2),D4 ;GET DST
EOR.L D4,D0 ;COMBINE DST WITH PATTERN
AND.L (A1)+,D0 ;APPLY REGION MASK
AND.L D5,D0 ;APPLY ALPHA MASK
EOR.L D4,D0 ;REAPPLY DST TO PATTERN
MOVE.L D0,(A2)+ ;PUT RESULT TO DST
DBRA D3,@mask ;LOOP ALL LONGS THIS ROW
BRA.s @inst ;LOOP BACK FOR more runs
@blit MOVE.L D6,D0 ;GET PATTERN DATA
MOVE.L (A2),D4 ;GET DST
EOR.L D4,D0 ;COMBINE DST WITH PATTERN
AND.L D5,D0 ;APPLY ALPHA MASK
EOR.L D4,D0 ;REAPPLY DST TO PATTERN
MOVE.L D0,(A2)+ ;PUT RESULT TO DST
DBRA D3,@blit ;LOOP ALL LONGS THIS ROW
BRA.s @inst ;LOOP BACK FOR more runs
rMASK8A equ @runs ;end of alpha changes block
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to PatConvert. If we were called from GetPicPixPat, set patXValid
; to -1 and return, otherwise patch to make direct pixpats work for offscreen gWorlds.
;
;=========================================================================================
;=========================================================================================
PATCONVERT PROC EXPORT
IMPORT PatDither,MakeScaleTbl
;------------------------------------------------------------------
;
; PROCEDURE PATCONVERT (PAT: PixPatHandle);
;
; Convert the specified pattern to the current depth and color table.
; Note: This routine is shared by patterns and cursors, which are parallel
; structures. Expand data for the pattern is kept in the patXMap handle, which
; is carefully unused if the structure is a cursor.
;
PARAMSIZE EQU 4
PAT EQU PARAMSIZE+8-4 ; handle to pattern
SAVESTK EQU -4 ; save the stack
WIDCNT EQU SAVESTK-2 ; width of pattern in pixels
HTCNT EQU WIDCNT-2 ; height of pattern in scans
HREPCNT EQU HTCNT-2 ; horizontal repetitions of pattern
VREPCNT EQU HREPCNT-2 ; vertical repetitions of pattern
PATROW EQU VREPCNT-2 ; rowbytes of src pattern
DstPix EQU PATROW-PMREC ; dst pixmap for calling stretch <1.5> BAL
VARSIZE EQU DstPix ; local vars <1.5> BAL
FromGetPicPixPat EQU $3313E
IndexedPatConvert EQU $30CFC
DirectPatConvert EQU $30D7E
GetDevPix EQU $28080
RSetHSize EQU $31450
cmpRA FromGetPicPixPat, (sp)
bne.s DoNormal
move.l 4(sp),a0 ;pixpatHandle
move.l (a0),a0 ;point to pixpat
move.w #-1,patXValid(a0)
RTD #4
DoNormal
LINK A6,#VARSIZE ; allocate stack frame
MOVEM.L D3-D7/A0/A2-A4,-(SP) ; save all registers
; A0 saved for SetFillPat
MOVE.L SP,SAVESTK(A6) ; save stack pointer
; get the dst pixel size in D6 and the src pixel size in D7
jsrROM GetDevPix ; get pointer to GDevice in A0
MOVE PixelSize(A0),D6 ; get dst pixel size
EXT.L D6 ; make long for translate loop
MOVE.L PAT(A6),A4 ; get the PixPat Handle
MOVE.L (A4),A1 ; point to the pixPat
MOVE patType(A1),D0 ; get the type of pattern
BMI.S NoDither ; => it's a cursor, no offset to set
MOVE.L patXMap(A1),A0 ; get handle to patXMap
MOVE.L (A0),A0 ; point to patXMap
CLR LastOfst(A0) ; we're expanding with offset 0
CMP #ditherPat,D0 ; does pat need to be dithered?
BNE.S NoDither ; => no, don't adjust
MOVE.L A4,-(SP) ; push pixPat handle
_PatDither ; create best-match dither
MOVE.L (A4),A1 ; point to the pixPat
NoDither MOVE.L PatMap(A1),A3 ; get the pixmap handle
MOVE.L (A3),A0 ; point to the pixmap
MOVE pixelSize(A0),D7 ; get source pixel size
EXT.L D7 ; make long for translate loop
; set up patXRow, patXHMask, patXVMask
MOVE rowBytes(A0),D0 ; get src rowbytes
AND #nuRBMask,D0 ; clear flag bits
MOVE D0,patRow(A6) ; save for expand loop
CLR HREPCNT(A6) ; assume no horizontal reps
CLR VREPCNT(A6) ; assume no vertical reps
LEA bounds+right(A0),A2 ; point to end of bounds
MOVE (A2),D4 ; get right
MOVE -(A2),D3 ; get bottom
SUB -(A2),D4 ; get width in pixels in D4
SUB -(A2),D3 ; get height in D3
MOVE D4,D0 ; get src width in pixels
SUBQ #1,D0 ; make it 0 based
MOVE D0,WIDCNT(A6) ; save src width in pixels
MOVE D3,D0 ; get height
SUBQ #1,D0 ; make it 0 based
MOVE D0,HTCNT(A6) ; save src height in pixels
; if the pattern is a cursor, skip repeat stuff
MOVE patType(A1),D0 ; get the type of pattern
BPL.S NoCrsr ; => not a cursor, get reps
LSR #3,D4 ; convert dst bits to bytes
MULU D6,D4 ; stretch to dst depth
BRA.S GotReps ; => don't replicate cursors
; If the pattern will fit into a long, repeat, if necessary, to fill the whole
; word. Also make the pattern 16 scans high. Set patXRow to 0 to indicate a 32*16 pattern.
NoCrsr MOVE.L patXMap(A1),A2 ; get handle to expanded info
MOVE.L (A2),A2 ; point to expanded info
MULU D6,D4 ; get dst width in bits
MOVEQ #32,D0 ; get number of bits in a long
DIVU D4,D0 ; get times to repeat to fit into long
SUBQ #1,D0 ; make repeat count 0 based
BMI.S NOREPS ; => no horizontal repetitions
MOVE D0,HREPCNT(A6) ; and set horizontal rep count
; pattern fits into a long, so set
CLR PATXROW(A2) ; flag to use the old blt routines
MOVEQ #4,D4 ; and set rowbytes to 4
MOVEQ #16,D0 ; get minimum number of vert lines
DIVU D3,D0 ; get 16 DIV height
CMP #1,D0 ; is it 1 or less?
BLT.S NOREPS2 ; => yes, no repetitions
MULU D0,D3 ; multiply height by repcount
SUBQ #1,D0 ; make VRepCnt 0 based
MOVE D0,VREPCNT(A6) ; and set vertical rep count
BRA.S REPS ; => patXRow already cleared
NOREPS LSR #3,D4 ; convert dst bits to bytes
NOREPS2 MOVE D4,PATXROW(A2) ; save expanded rowbytes
REPS MOVE D4,D0 ; copy expanded rowBytes
SUBQ #1,D0 ; HMASK := $FFFC AND (rowbytes-1)
AND #$FFFC,D0 ; mask to long boundary
MOVE D0,PatXHMask(A2) ; save HMask
MOVE D4,D0 ; get (adjusted) rowbytes
MULU D3,D0 ; VMASK := rowbytes*height - 1
SUBQ #1,D0 ; make it a mask
MOVE D0,PatXVMask(A2) ; save VMask
; Calc total size of the dst and set the size of patXData
GotReps MOVE D4,D0 ; get (adjusted) width in bytes
MULU D3,D0 ; multiply by (adjusted) height
MOVE.L (A4),A0 ; point to the pixPat
MOVE.L patXData(A0),A0 ; get the handle to expanded bits
jsrROM RSetHSize ; set to proper size
; Allocate pixel translate table on top of stack and initialize
cmp.W #8,d7 ; is src direct data? <1.5> BAL
bgt.s DirectPixPat ; yes, go call stretchbits <1.5> BAL
jmpROM IndexedPatConvert
; MOVE.L (A3),-(SP) ; push pixMap pointer
; MOVE #$20,-(SP) ; pass srcAverage as a mode (so colors are used)
; _MakeScaleTbl ; make translate table
DirectPixPat
MOVE.L (A4),A0 ; point to the pixPat
MOVE.L patData(A0),A0 ; get the src data handle
MOVE.L (a0),a0 ; get the src data ptr
MOVE.L (A3),A1 ; point to the pixmap
MOVE.L a0,baseAddr(a1) ; point the baseAddr to the patData
jsrROM GetDevPix ; get pointer to GDevice in A0
lea dstPix(a6),a1 ; point to dst pixMap
MOVEQ #PMREC/2-1,D0 ; make a local copy of dst gdpmap
@NXTWORD MOVE (A0)+,(A1)+ ;
DBRA D0,@NXTWORD ;
lea dstPix+bounds+top(a6),a0 ; set up dstPix for patXData
clr.w dstPix+pmVersion(a6) ; base address is pointer <24JUL90 KON>
jmpROM DirectPatConvert
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Register A2 is getting trashed when setting CCursor on mulitple device systems
; This patches that baby out!
;
;=========================================================================================
;=========================================================================================
PatchJSetCCursor PROC EXPORT
ciGETMAINCRSR EQU $2E484
ciERASECURSOR EQU $2E27A
ciDRAWCURSOR EQU $2E2BC
;_______________________________________________________________________
;
; PROCEDURE SetCCursor(cCrsr: CCrsrHandle);
;
; This procedure copies the data in the specified color cursor into the
; system's cursor save area. If the depth > 2, it expands it.
SetCCursor MOVEM.L D3-D4/A2-A4,-(SP) ;save work registers
move.l 24(sp),a2 ;get ccrsrHandle <BAL 21Jun88>
move.l a2,a0 ;make a copy
_HGetState
move d0,-(sp) ;save state for later
move.l a2,a0 ;make a copy
_HLock
MOVE.L (a2),A2 ;GET POINTER TO NEW CURSOR
MOVE.L ([CRSRPTR]),A3 ;point to current cursor (LOCKED)
MOVE.L crsrID(A2),D0 ;and get ID of new cursor
CMP #CCrsrPat,ccType(A3) ;is current cursor a color cursor?
BNE.S NotCC ;=>no, it has definitely changed
CMP.L ccID(A3),D0 ;same as current one?
BEQ SCCDONE ;=>yes, just return
NotCC MOVE.B #1,CRSRBUSY ;flag the cursor as busy
MOVE.L D0,ccID(A3) ;set new ID
LEA crsr1Data(A2),A0 ;point to old-cursor data
LEA THECRSR,A1 ;put it here
MOVEQ #16,D0 ;data+mask+hotspot = 17 longs
@0 MOVE.L (A0)+,(A1)+ ;copy data
DBRA D0,@0 ;until done
LEA crsr1Data(A2),A0 ;point to old-cursor data
LEA CCLASTCRSR(A3),A1 ;save here to indicate cursor changed
MOVEQ #7,D0 ;move 8 longs
@1 MOVE.L (A0)+,(A1)+ ;copy data
DBRA D0,@1 ;=>loop until done
MOVE crsrType(A2),ccType(A3) ;copy the type
; NOTE: ALL THE DST HANDLES ARE LOCKED, BUT THEY HAVE BEEN SET TO THE PROPER SIZE
MOVE.L crsrMap(A2),-(SP) ;push src pixMap handle
MOVE.L ccMap(A3),-(SP) ;push dst pixMap handle
_CopyPixMap ;copy the pixMap
MOVE.L crsrData(A2),-(SP) ;push src data handle
MOVE.L ccData(A3),-(SP) ;push dst data handle
_CopyHandle ;copy the cursor data
; FOR EACH ACTIVE SCREEN DEVICE, EXPAND CURSOR, IF NECESSARY
MOVE.L DEVICELIST,D4 ;D4 = CURRENT DEVICE
MOVE.L D4,A4 ;GET HANDLE TO CURRENT DEVICE
NXTSCR MOVE.L (A4),A4 ;A4 = POINTER TO CURRENT DEVICE
TST.W GDFLAGS(A4) ;IS THE DEVICE ACTIVE?
BPL CHKNXT ;=>NO, CHECK NEXT DEVICE
;ACTIVE DEVICES ARE LOCKED DOWN
MOVE.L GDPMAP(A4),A0 ;GET HANDLE TO DEVICE'S PIXMAP
MOVE.L (A0),A0 ;POINT TO DEVICE'S PIXMAP
MOVE PIXELSIZE(A0),D3 ;GET DEVICE'S PIXELSIZE
; IF THE PATTERN IS PRE-EXPANDED TO THE RIGHT DEPTH, JUST COPY THAT DATA
CLR GDCCDEPTH(A4) ;flag to expand one-bit data
MOVE CRSRXVALID(A2),D0 ;is there pre-expanded data?
BEQ.S GOEXP ;=>no, do expansion
CMP D3,D0 ;is the expanded data the right depth?
BNE.S GOEXP ;=>no, expand from the source
MOVE D0,GDCCDEPTH(A4) ;else copy the expanded depth
MOVE.L crsrXData(A2),-(SP) ;push the src xdata handle
MOVE.L CCXDATA(A3),-(SP) ;push the dst xdata handle
_CopyHandle ;and copy it
BRA.S CHKNXT ;=>data already expanded, just exit
GOEXP CMP #CCRSRPAT,CCTYPE(A3) ;IS IT A COLOR CURSOR?
BNE.S DONEONE ;=>NO, EXIT WITH DEPTH = 0
CMP #2,D3 ;IS DEPTH GREATER THAN 2?
BLE.S DONEONE ;=>NO, EXIT WITH DEPTH = 0
MOVE D3,GDCCDEPTH(A4) ;RECORD THE EXPANDED DEPTH
MOVE.L GDCCXDATA(A4),CCXDATA(A3) ;GET DEVICE'S EXPANDED DATA FOR PATCONVERT
MOVE.L THEGDEVICE,-(SP) ;SAVE GRAFDEVICE (USED BY PATCONVERT)
MOVE.L D4,THEGDEVICE ;SET IT TO CURRENT DEVICE
MOVE.L CRSRPTR,-(SP) ;PUSH HANDLE TO CURSOR (LOCKED)
_PATCONVERT ;AND EXPAND TO CURRENT DEPTH
MOVE.L (SP)+,THEGDEVICE ;RESTORE GRAFDEVICE
; EXPAND THE MASK TO THE CURRENT DEPTH
MOVE D3,D0 ;GET DEPTH
MOVEQ #0,D1 ;DEFAULT SHIFT = 0
NXTSHFT1 LSR #1,D0 ;CHECK NEXT DEPTH BIT
BCS.S GOTSHFT1 ;=>GOT SHIFT
ADDQ #1,D1 ;ELSE ADD ONE TO SHIFT
BRA.S NXTSHFT1 ;LOOP UNTIL WE HIT A ONE
GOTSHFT1 LEA THECRSR+MASK,A0 ;SRC = CURSOR MASK
MOVE.L ([GDCCXMASK,A4]),A1 ;POINT TO EXPANDED MASK (LOCKED)
move.l a2,d4 ;save pointer to new cursor <25APR91 KON>
MOVE.L A1,A2 ;GET START OF DST BUFFER <27May87 EHB>
MOVE #32,D0 ;GET #BYTES OF SOURCE <27May87 EHB>
LSL D1,D0 ;MULTIPLY BY DEPTH <27May87 EHB>
ADD D0,A2 ;POINT TO END OF BUFFER <27May87 EHB>
move.l ExTblPtr,A3 ;POINT TO ROUTINE TABLE
add.l 0(A3,D1*4),A3 ;USE DEPTH TO SELECT ROUTINE
MOVEQ #0,D0 ;CLEAR HIGH PART OF D0
JSR (A3) ;EXPAND 32*DEPTH BYTES
MOVE.L ([CRSRPTR]),A3 ;GET BACK POINTER TO CURSOR (LOCKED)
move.l d4,a2 ;restore pointer to new cursor <25APR91 KON>
DONEONE MOVE GDCCDEPTH(A4),D0 ;GET EXPANDED DEPTH
ADD D0,D0 ;DOUBLE IT
MOVE D0,GDCCBYTES(A4) ;AND SAVE AS CURSOR'S ROWBYTES
CHKNXT MOVE.L GDNEXTGD(A4),D4 ;IS THERE A NEXT DEVICE?
MOVE.L D4,A4 ;GET HANDLE TO NEXT DEVICE
BNE NXTSCR ;=>THERE IS ONE, PREPARE ITS CURSOR
jsrROM ciGETMAINCRSR ;RESTORE EXPAND DATA FOR MAIN CURSOR
jsrROM ciERASECURSOR ;HIDE THE OLD CURSOR
jsrROM ciDRAWCURSOR ;DISPLAY THE NEW CURSOR
SCCDONE CLR.B CRSRBUSY ;CURSOR NOT BUSY ANYMORE
move (sp)+,d0 ;get ccrsrhandle state
move.l 24(sp),a0 ;get ccrsrHandle
_HSetState
MOVEM.L (SP)+,D3-D4/A2-A4 ;restore work registers
MOVE.L (SP)+,(SP) ;strip parameter
RTS ;and return
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Obscure-show-hide leaves crsr hidden only, Obscure-hide-show leaves crsr
; obscured only.
;
;=========================================================================================
;=========================================================================================
PatchJShowCursor PROC EXPORT
ciROMDrawCursor EQU $2E2BC
ciROMDoneSho EQU $2E2DC
ShieldDepth EQU $0D4C ;this equate should not be here
;_______________________________________________________________________
;
; SHOWCURSOR - Called from CrsrVBLTask and via Jump Table.
;
; Adds 1 to CRSRSTATE and paints cursor if zero and cursor is
; not already visible.
;
ShowCursor
MOVE.B #1,CRSRBUSY ;MARK CHANGE IN PROGRESS
TST ShieldDepth ;Any shielding?
BEQ.s @2
@1 SUBQ #1,ShieldDepth ;If so, this ShowCursor unshields,
BRA.s DrawCursor ;but doesn't up the cursor level.
@2 ADDQ #1,CRSRSTATE ;CURSOR HIDDEN ONE LESS DEEP
bmi.s DoneSho
beq.s DrawCursor ;<KON 25JUN90>
clr.b CrsrObscure ;unobscure cursor if level went past zero <KON 25JUN90>
;fall into DrawCursor
;________________________________________________________________________
; DrawCursor is much like ShowCursor, but doesn't increment the CrsrState <dvb 19sep88>
DrawCursor
jmpROM ciROMDrawCursor
DoneSho
jmpROM ciROMDoneSho
ENDPROC
;
; <124> Bring back GetCPixel until the Future arrives
;
if not(TheFuture) then
;=========================================================================================
;=========================================================================================
;
; Patch to getPixel and getCPixel so that SwapMMUMode is called if pixmap needs 32-bit
; addressing (pmVersion = 4). These calls are in QDUtil.a.
;
;=========================================================================================
;=========================================================================================
GetCPixel FUNC EXPORT
EXPORT GETPIXEL
IMPORT PortToMap
ciMMUModeOK EQU $2F018
ciGetPixelDone EQU $2F070
;---------------------------------------------------------
;
; FUNCTION GetPixel(h,v: INTEGER): BOOLEAN;
; PROCEDURE GetCPixel(h,v: INTEGER; myColor: RGBColor);
;
; Returns TRUE if the pixel at (h,v) is set to black.
; h and v are in local coords of the current grafport.
;
; WATCH OUT FOR STACK TRICKERY WHEN GETCPIXEL CALLS GETPIXEL!!
;
; CLOBBERS A0,A1,D0,D1,D2
;
PARAMSIZE EQU 4
RETURN EQU PARAMSIZE+8 ;ADDRESS OF BOOLEAN/RGBCOLOR
HLOC EQU PARAMSIZE+8-2 ;HORIZONTAL POSITION
VLOC EQU HLOC-2 ;VERTICAL POSITION
VARSIZE EQU 0 ;TOTAL SIZE OF LOCALS
MOVE.L 8(SP),-(SP) ;PUSH H,V
MOVEQ #1,D2 ;ROUTINE = GETCPIXEL
BSR.S SHARE ;USE COMMON CODE
RTD #8 ;STRIP PARAMS AND RETURN
GETPIXEL
MOVEQ #0,D2 ;ROUTINE = GETPIXEL
SHARE LINK A6,#VARSIZE ;ALLOCATE STACKFRAME
MOVEM.L D4-D5/A2-A3,-(SP) ;SAVE WORK REGISTERS
MOVE.L THEGDEVICE,-(SP) ;SAVE CURRENT GRAFDEVICE
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET THEPORT
_PORTTOMAP ;GET BIT/PIXMAP IN A0
; GET GLOBAL COORDINATES OF VLOC INTO D4 AND HLOC INTO D5
OLDRB MOVE VLOC(A6),D4 ;GET VERTICAL
SUB BOUNDS+TOP(A0),D4 ;CONVERT TO GLOBAL COORDS
MOVE HLOC(A6),D5 ;GET HORIZ COORD
SUB BOUNDS+LEFT(A0),D5 ;CONVERT TO GLOBAL
; IS IT FROM THE SCREEN?
MOVE.L MAINDEVICE,A2 ;GET MAIN DEVICE
MOVE.L (A2),A2 ;POINT TO IT
MOVE.L GDPMAP(A2),A2 ;GET PIXMAP HANDLE
MOVE.L (A2),A2 ;POINT TO PIXMAP
MOVE.L BASEADDR(A0),D1 ;GET PORT'S BASEADDR
CMP.L BASEADDR(A2),D1 ;SAME AS SCREEN'S?
seq.b -(sp) ;push crsrFlag @@@@ BAL 14Apr88
move.l a0,a3 ;save pixmap in a3
BNE.S NOTSCRN ;=>NO, NOT SCREEN
; IT IS FROM THE SCREEN! Shield the Cursor. @@@@ BAL 14Apr88
MOVE D5,-(SP) ;PUSH GLOBAL LEFT
MOVE D4,-(SP) ;PUSH GLOBAL TOP
MOVE D5,-(SP) ;PUSH GLOBAL RIGHT
MOVE D4,-(SP) ;PUSH GLOBAL BOTTOM
MOVE.L JShieldCursor,A1 ;get lo mem vector
JSR (A1) ;and call it
MOVE.L DEVICELIST,A3 ;GET FIRST IN DEVICE LIST
DONXT MOVE.L (A3),A2 ;POINT TO DEVICE
TST GDFLAGS(A2) ;IS DEVICE ACTIVE?
BPL.S NXTDEV ;=>NO, NOT ACTIVE
LEA GDRECT(A2),A1 ;POINT TO DEVICE'S RECT
CMP (A1)+,D4 ;IS VERTICAL < GDRECT.TOP ? <SMC 18SEP90>
BLT.S NXTDEV ;=>YES, CHECK NEXT DEVICE <SMC 18SEP90>
CMP (A1)+,D5 ;IS HORIZONTAL < GDRECT.LEFT ? <SMC 18SEP90>
BLT.S NXTDEV ;=>YES, CHECK NEXT DEVICE <SMC 18SEP90>
CMP (A1)+,D4 ;IS VERTICAL >= GDRECT.BOTTOM ?
BGE.S NXTDEV ;=>YES, CHECK NEXT DEVICE
CMP (A1)+,D5 ;IS HORIZONTAL >= GDRECT.RIGHT ?
BLT.S GOTDEV ;=>NO, FOUND DEVICE
NXTDEV MOVE.L GDNEXTGD(A2),D0 ;GET HANDLE TO NEXT DEVICE
MOVE.L D0,A3 ;KEEP IN A3
BNE.S DONXT ;=>THERE IS A DEVICE
BRA DONE ;=>DEVICE NOT FOUND, JUST RETURN
; FOUND THE DEVICE! SET DEVICE AND OFFSET POINT TO DEVICE LOCAL COORDINATES
GOTDEV MOVE.L A3,THEGDEVICE ;MAKE DEVICE CURRENT
LEA GDRECT(A2),A1 ;POINT TO DEVICE'S RECT
SUB (A1)+,D4 ;OFFSET VERTICAL
SUB (A1)+,D5 ;OFFSET HORIZONTAL
MOVE.L GDPMAP(A2),A3 ;GET PIXMAP HANDLE
MOVE.L (A3),d0 ;POINT TO PIXMAP
_rTranslate24To32 ;strip off high byte @@@@ BAL 14Apr88
move.l d0,a3
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
Needs32BitMode
move.b #$ff,(sp) ;flag the fact that MMU mode must be swapped <KON 20JUN90>
moveq #true32b,d0 ;switch to 32 bit addressing
move.w d2,-(sp) ;save color/ bw flag across call
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a2, d0/d2)
move.w (sp)+,d2 ;restore flag in d2
;save previous state in d0 for later
bra.s MMUModeOK
NOTSCRN
;
; Check if pixmap needs 32-bit addressing <KON 20JUN90>
;
baseAddr32Bit EQU 2
tst.w rowbytes(a3) ; <KON 20JUN90>
bpl.s MMUModeOK ;it's a bitmap <KON 20JUN90>
btst #baseAddr32Bit,pmVersion+1(a3) ; <KON 20JUN90>
bne.s Needs32BitMode ;pixmap needs 32-bit addressing <KON 20JUN90>
MMUModeOK
jmpROM ciMMUModeOK
DONE
jmpROM ciGetPixelDone
ENDPROC
endif ; <124> of not TheFuture
;=========================================================================================
;=========================================================================================
;
; New call KopyMask is copyMask with a mode and a rgn parameter.
;
;=========================================================================================
;=========================================================================================
KopyMask PROC EXPORT
IMPORT PORTTOMAP,BITSTOMAP
CMDevLoopinROM EQU $35990
;--------------------------------------------------------------
;
; PROCEDURE KopyMask(srcBits,maskBits,dstBits: BitMap;
; srcRect,maskRect,dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle *);
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE EQU 30 ;total bytes of params
SRCBITS EQU PARAMSIZE+8-4 ;long, addr of BitMap
MASKBITS EQU SRCBITS-4 ;long, addr of BitMap
DSTBITS EQU MASKBITS-4 ;long, addr of BitMap
SRCRECT EQU DSTBITS-4 ;long, addr of Rect
MASKRECT EQU SRCRECT-4 ;long, addr of Rect
DSTRECT EQU MASKRECT-4 ;long, addr of Rect
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
VARSIZE EQU 0
share LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE WORK REGISTERS FOR DEVLOOP
; SET UP REGISTERS FOR CALLING CMDEVLOOP
MOVE.L DSTBITS(A6),A1 ;GET DST BIT/PIXMAP
MOVE.L MASKBITS(A6),D0 ;GET MASK BIT/PIXMAP
MOVE.L MASKRECT(A6),D1 ;GET MASK RECTANGLE
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;GET THE PORT IN A3 FOR DEVLOOP
MOVE.L WIDEOPEN(A4),D2 ;ASSUME NO CLIPPING FOR FIRST RGN
MOVE.L D2,D3 ;ASSUME NO CLIPPING FOR SECOND RGN
; PUSH PARAMETERS FOR CALLING CMDEVLOOP (SAME AS STDBITS)
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRC BIT/PIXMAP
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRC RECTANGLE
MOVE.L DSTRECT(A6),-(SP) ;PUSH DST RECTANGLE
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK ;WAS IT NIL ?
MOVE.L D2,(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK
;-----------------------------------------------------
;
; TEST IF DST IS TO THEPORT, (IF SO WE CLIP)
;
SRCOK MOVE.L DSTBITS(A6),A0 ;POINT TO DSTBITS
_BITSTOMAP ;GET POINTER TO BIT/PIXMAP IN A0
MOVE.L A0,A1 ;SAVE IN A1
MOVE.L A3,D4 ;IS THEPORT NIL ?
BEQ.S NOTPORT ;YES, NOT TO THEPORT
BTST #0,D4 ;IS THEPORT ODD ?
BNE.S NOTPORT ;YES, NOT TO THEPORT
MOVE.L D4,A0 ;GET THEPORT
_PORTTOMAP ;CONVERT PORT TO BIT/PIXMAP
MOVE.L BASEADDR(A0),D4 ;GET PORTBITS.BASEADDR
CMP.L BASEADDR(A1),D4 ;IS DST BASEADDR SAME ?
BNE.S NOTPORT ;NO, NOT TO THEPORT
MOVE.L BOUNDS(A0),D4 ;GET PORT BOUNDS TOPLEFT
CMP.L BOUNDS(A1),D4 ;IS BOUNDS TOPLEFT SAME ?
BNE.S NOTPORT ;=>NO, NOT TO THE PORT
MOVE.L CLIPRGN(A3),D2 ;YES, CLIP TO CLIPRGN
MOVE.L VISRGN(A3),D3 ;AND TO VISRGN
NOTPORT MOVE.L DSTBITS(A6),A1 ;Pass DSTBITS (not derefed) <BAL 28May89>
jsrROM CMDevLoopinROM ;AND DRAW THE IMAGE
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'KopyMask'
;=========================================================================================
;=========================================================================================
;
; DelSearch and DelComp need to call Translate24to32 on the address before searching
; for it in the list of search and comp procs. Due a screwup in the Erickson ROM, these
; routines are only installed if it's a ci class ROM. This is done below the EntryTable
; for the rest of the traps.
;
;=========================================================================================
;=========================================================================================
DelComp PROC EXPORT ; <C666/22Jan87> DAF
ciDelCompEntry EQU $3CAF4
MOVE.L 4(SP),D0 ; get the CompProc pointer
_rTranslate24To32 ; clean up the address <KON 29May90>
move.l d0,d1 ; put proc pointer where the ROM expects it
jmpROM ciDelCompEntry
ENDPROC
DelSearch PROC EXPORT ; <C666/22Jan87> DAF
ciDelSearchEntry EQU $3CAC4
MOVE.L 4(SP),D0 ; get the SearchProc pointer
_rTranslate24To32 ; clean up the address <KON 29May90>
move.l d0,d1 ; put proc pointer where the ROM expects it
jmpROM ciDelSearchEntry
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Pointer to color was incorrect when a comp proc is installed. The offset should
; be 10 (not 8) to compensate for byte result.
;
;=========================================================================================
;=========================================================================================
InvertColor PROC EXPORT
ciDefComp EQU $3C536
ciInvertColorEntry EQU $3C51A
;
; procedure InvertColor ( VAR myColor : RGBColor );
;
; This procedure takes an RGBColor, calculates its inverse using the current
; inverse rules, then updates the provided RGBColor. It only uses the
; compProc interface if the default is not called.
;
MOVE.L A2,-(SP) ; save a register <C601/07Jan87> DAF
MOVE.L ([theGDevice]),A2 ; get a pointer to the device port
MOVE.L GDCompProc(A2),D0 ; get the head of the complement chain
@1
BEQ.S DefComp ; if NIL, then apply default rule
MOVE.L D0,A2 ; save the pointer <C601/07Jan87> DAF
MOVE.L D0,A0 ; set up to lock this element <C666/22Jan87> DAF
_HLock ; lock it down so that A2 will be valid after the JSR <C666/22Jan87> DAF
CLR.B -(SP) ; room for a boolean result
MOVE.L 8+2(SP),-(SP) ; push the pointer to the color <26MAR90 KON>
jmpROM ciInvertColorEntry
; MOVE.L (A0),A0 ; get the element pointer <C666/22Jan87> DAF
; MOVE.L CompProc(A0),A0 ; get the complement proc ptr <C666/22Jan87> DAF
; JSR (A0) ; execute routine
; MOVE.L A2,A0 ; set up for HUnlock <C666/22Jan87> DAF
; _HUnlock ; release the compElement <C666/22Jan87> DAF
; TST.B (SP)+ ; test the result
; BNE.S FoundComp ; if result = TRUE then quit
; MOVE.L (A2),A0 ; get the compElement pointer again <C666/22Jan87> DAF
; MOVE.L NxtComp(A0),D0 ; get pointer to next <C666/22Jan87> DAF
; BRA.S @1 ;
;FoundComp
; MOVE.L (SP)+,A2 ; restore the register <C601/07Jan87> DAF
; RTD #4 ; and go home
; the default procedure is VERY simple. It just gets the complement of each
; component. It always returns a sucessful result.
DefComp
jmpROM ciDefComp
; MOVE.L 8(SP),A0 ; get pointer to RGBColor
; NOT.W (A0)+ ; complement red
; NOT.W (A0)+ ; complement green
; NOT.W (A0) ; complement bleu, svp.
; BRA.S FoundComp ; and it always works too.
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patchd to MakeITable to first search temp memory, then system zone, and finally
; theZone.
;
;=========================================================================================
;=========================================================================================
MakeITable PROC EXPORT
EXPORT DisposeTempBuffer
FromMakeITable EQU $3C11C
ciDisposeTempBuffer EQU $31510
ciNotTemp2 EQU $3BEE4
;----------------------------------------------------------------
;
; PROCEDURE MakeITable (CTABH: CTabHandle; ITabH: ITabHandle; res:integer);
;
; This procedure builds an inverse lookup table with res bits per channel
; based on the specified color table. Algorithm by MJ Potel, based on Voronoi theory.
; Algorithm modified by Art Cabral, adding a linked list at the end of the table
; which is used to find hidden colors in Color2Index.
;
; Still to be done : Consolidate Queue and table into 1 memory block
; Convert to bitmap/iLUT form
; Eliminate BTST for TST.B
;
; 1. Use supplied cTabHandle and iTabHandle. This makes it context independent.
; 2. Compress directly into iTable. A little faster.
; 3. Shouldn't need to to error checking in QUEUE and DEQUEUE
UNDEF EQU $8000 ; hi bit on
BOUND EQU $7FFF ; non-neg, large unused index
QInTempBit EQU $00
ITableInTempBit EQU $01
PARAMSIZE EQU 10 ; total bytes of params
CTabH EQU PARAMSIZE+8-4 ; Color table handle
ITabH EQU CTabH-4 ; ITable handle
RES EQU ITabH-2 ; entry size
QStart EQU -4 ; pointer to the queue
SvZone EQU QStart-4 ; save the current zone
TblH EQU SvZone-4 ; copy of our temp ITable
TblSize EQU TblH-4 ; size of our temp ITable
InfoOffset EQU TblSize-4 ; offset to ITInfoTable from ITabH
isTmpHandle EQU InfoOffset-2 ; boolean->true if TblH is a TmpMem handle
QHandle EQU isTmpHandle-4 ; Handle for queue <28Feb90 KON>
VARSIZE EQU QHandle
LINK A6,#VARSIZE ; set up a stack frame
MOVEM.L A2-A5/D3-D7,-(SP) ; save 'em all
; move.l theZone,SvZone(A6) ; save the current heap zone for later restore <16Jan90> BAL
CLR.W QDErr ; clear QDError flag <C666/22Jan87> DAF
MOVE res(A6),D7 ; get the channel size <C777/12Feb87> EHB
CMP.L #-1,theGDevice ; if -1, then it's uninitialized <C777/12Feb87> DAF
BEQ.S @ResCheck ; OK, so continue <C777/12Feb87> DAF
@GDevOK
MOVE.L ([theGDevice]),A0 ; get a pointer to the current device <C777/12Feb87> DAF
; test the parameters. If ITabH or CTabH are NIL, substitute handles from theGDevice <C695/26Jan87> DAF
TST.L ITabH(A6) ; is ITabH NIL? <C695/26Jan87> DAF
BNE.S @DoCTabH ; no, so continue <C695/26Jan87> DAF
MOVE.L GDITable(A0),ITabH(A6) ; stick theGDevice's ITabH in stack frame <C695/26Jan87> DAF
@DoCTabH
TST.L CTabH(A6) ; is CTabH NIL? <C695/26Jan87> DAF
BNE.S @DoITabRes ; no, so continue <C695/26Jan87> DAF
MOVE.L ([GDPMap,A0]),A1 ; get pixMap's handle <C695/26Jan87> DAF
MOVE.L PMTable(A1),CTabH(A6) ; get the device colorTable's pointer <C695/26Jan87> DAF
@DoITabRes
; get the ITable resolution
TST D7 ; test the channel size <C777/09Feb87> EHB
BNE.S @ResCheck ; if valid, continue <C695/26Jan87> DAF
; the res parameter was 0, so get theGDevice's preferred resolution <C777/09Feb87> DAF
MOVE.W GDResPref(A0),D7 ; get the preferred ITabRes <C695/26Jan87> DAF
BNE.S @ResSubst ; if non-zero, then continue <C777/09Feb87> DAF
MOVEQ #4,D7 ; if resPref=0, then force to 4 <C777/09Feb87> DAF
@ResSubst
MOVE.W D7,res(A6) ; and put it in the stack frame <C695/26Jan87> DAF
@ResCheck
CMP.W #2,D7 ; don't accept res≤2 <C695/26Jan87> DAF
BLE.S @BadRes ; <C695/26Jan87> DAF
CMP.W #6,D7 ; or ≥ 6 <C695/26Jan87> DAF
BLT.S @ResOK ; <C695/26Jan87> DAF
@BadRes MOVE.W #cResErr,QDErr ; mark the error and quit <C695/26Jan87> DAF
BRA MITDone ; <C695/26Jan87> DAF
@ResOK ; <C695/26Jan87> DAF
; Calculate the size of the compressed table and verify the handle
MOVE D7,D1 ; get the channel size <C733/02Feb87> DAF
MOVEQ.L #1,D0 ; prime the register
LSL.L D1,D0 ; calculate 2^^res
LSL.L D1,D0 ; square it
LSL.L D1,D0 ; cube it
ADD.L #ITTable,D0 ; make room for everybody
MOVE.L D0,InfoOffset(A6) ; save offset to end of table
ADD.L #ITExtraSize,D0 ; make room for InfoTable
MOVE.L ITabH(A6),A0 ; get the ITable handle
TST.L (A0) ; is the table purged? <C751/03Feb87> DAF
BEQ.S @1 ; yes, so Realloc it <C751/03Feb87> DAF
_SetHandleSize ; set the size <C751/03Feb87> DAF
BRA.S @2 ; and continue <C751/03Feb87> DAF
@1
_ReallocHandle ; <C751/03Feb87> DAF
@2
BEQ.S @SizeOK ; => size ok, so continue <C733/02Feb87> DAF
MOVE.W #CNoMemErr,QDErr ; report this error <C733/02Feb87> DAF
BRA MITDone ; and quit <C733/02Feb87> DAF
@SizeOK
;--------------------------------------------------------------------- <BAL 15Mar89>
;
; Cruise through the clut and check if all non-reserved entries are grays.
; If they are then build a gray Itab and set flag in Info header to indicate grayness.
;
move.l CTabH(a6),a0 ;
move.l (a0),a0 ; get CTab ptr
move.w ctSize(a0),d0 ; get clut entries-1
lea ctTable(a0),a1 ; point at first clut entry
@nextEntry
move.l (a1)+,d1 ; pick up value,red
move.l (a1)+,d2 ; pick up green,blue
cmp.w d1,d2 ; red==blue?
bne.s @notGray ;
swap d2 ; get green
cmp.w d1,d2 ; red==green?
bne.s @notGray ;
@skippy dbra d0,@nextEntry ; continue checking
_MakeGrayITab ; go make special Gray ITab
bra MITDone ; all done
@notGray
btst #ReserveBit+24,d1 ; is this entry reserved?
bne.s @skippy ; don't check reserved entries
;--------------------------------------------------------------------- <BAL 15Mar89>
AdjZone
;
; Later we regain control at DisposeTempBuffer which is called only if isTmpHandle
; is non-zero. Since we only use the low bits to signal whether or not the handle
; resides in tmp memory or not, we set high bits to force the call to DisposeTempBuffer.
move.w #$8080,isTmpHandle(a6) ;assume handles are not in temp memory <28Feb90 KON>
;and set high bits so DisposeTempBuffer is called later
; allocate space on the heap for the queue, reading queue size from resource
SUBQ #4,SP ; make room for the function return <C835/20Feb87> DAF
MOVE.L #'mitq',-(SP) ; push the queue size resource type <C835/20Feb87> DAF
CLR.W -(SP) ; want mitq=0 <C835/20Feb87> DAF
_rGetResource ; system first, then ROM <C835/20Feb87> DAF
MOVE.L (SP)+,A0 ; get the handle <C835/20Feb87> DAF
MOVE.L (A0),A0 ; get the pointer in A0 <C835/20Feb87> DAF
MOVE.L -12(A0,D7*4),D0 ; get the queue size (adjust for no 1 or 2 bit resolutions) <C835/20Feb87> DAF
MOVE.L D0,D3 ; hold it for a second
bsr NewHandleTempSysApp ;get memory <28Feb90 KON>
BNE MakeIErrLate ; if there was an error report it
;
; Got a handle. Check which heap it's in and lock it.
;
tst.w d1 ;d1=0 -> memory in temp heap <28Feb90 KON>
bne.s @notTemp1 ; <28Feb90 KON>
bset #QInTempBit, isTmpHandle(a6) ;Main ITable is in temp memory <28Feb90 KON>
@notTemp1
;
; want a ptr, so lock and deref handle
;
move.l a0,QHandle(a6) ;save QHandle <28Feb90 KON>
_HLock ;preserves a0 <28Feb90 KON>
move.l (a0),a0 ;deref it <28Feb90 KON>
MOVE.L A0,QStart(A6) ; save the starting addr in stack frame
ADD.L D3,A0 ; compute the addr of the queue end
MOVE.L A0,A5 ; keep the queue end here
; allocate BIG space on the heap for the ITable (to be shrunken and moved to sysheap later)
MOVEQ #1,D6 ; prime the register
LSL.L D7,D6 ; calculate 2^^res
MOVE.L D6,D5 ; save here for boundary setting
ADDQ #2,D6 ; increase by 2 for the boundary
MOVE.L D6,D0 ; get it in a working register
MULU.W D6,D0 ; square it
MULU.W D6,D0 ; cube it
ADD.L D0,D0 ; table size -> words
MOVE.L D0,TblSize(A6) ; save size of table
bsr.s NewHandleTempSysApp ;search everywhere for some memory <28Feb90 KON>
bne.s MakeIErr ;failed! <28Feb90 KON>
;
; Got memory, check which heap it's in
;
tst.w d1 ;d1=0 -> memory in temp heap <28Feb90 KON>
bne.s @notTemp2 ; <28Feb90 KON>
bset #ITableInTempBit, isTmpHandle(a6) ;Main ITable is in temp memory <28Feb90 KON>
@notTemp2
jmpROM ciNotTemp2
; MOVE.L A0,TblH(A6) ; save temporary table
; MOVE.L (A0),A0 ; dereference the handle
; MOVE.L A0,A3 ; set up the table base ptr
MakeIErr
MOVE.W #CTempMemErr,QDErr ; report a table allocation error
bra.s DisposeQ
MakeIErrLate
MOVE.W #CTempMemErr,QDErr ; report a table allocation error
BRA.S MITDone
;=========================================================================================
;=========================================================================================
;
; ComeFrom MakeITable patch on DisposeTempBuffer to do clean up for MakeITable
;
;=========================================================================================
;=========================================================================================
DisposeTempBuffer
cmpRA FromMakeITable, (sp)
beq.s @DoMakeITableDispose
jmpROM ciDisposeTempBuffer ;not from MakeITable: Go back to ROM
@DoMakeITableDispose
;
; remove return address so registers are restored properly
;
addq #4, sp
; a0 has handle to dispose
btst #ITableInTempBit, isTmpHandle(a6) ;is handle in temp memory? <28Feb90 KON>
beq.s @notTmp ; no, use normal dispose <2.2> BAL
_DisposeTempBuffer ; bag it <2.2> BAL
bra.s @allGone ; continue <2.2> BAL
@notTmp _DisposHandle ; release it
@allGone
;
; dispose of the memory for the Queue
;
DisposeQ ; <24Apr87> DAF
MOVE.L QHandle(A6),A0 ; release the queue <28Feb90 KON>
btst #QInTempBit, isTmpHandle(a6) ;is Queue in temp memory <28Feb90 KON>
beq.s @QnotTmp ; no, use normal dispose <28Feb90 KON>
_DisposeTempBuffer ; bag it <28Feb90 KON>
bra.s @QallGone ; continue <28Feb90 KON>
@QnotTmp _DisposHandle ; release it <28Feb90 KON>
@QallGone ; <28Feb90 KON>
MITDone ; <C695/26Jan87> DAF
; MOVE.L SvZone(A6),theZone ; always restore the zone (needed for error exits) <BAL>
MOVEM.L (SP)+,A2-A5/D3-D7 ; restore registers
UNLK A6 ; bag the stack frame
RTD #ParamSize ; flush parameters and return home <C733/02Feb87> DAF
;----------------- Subroutine to hunt for memory -----------------------------
NewHandleTempSysApp
;
; Called with requested size in d0. Routine first tries to get memory first in
; multifinder temp memory, then sys heap, then app heap. If memory found in
; temp memory, d1 returns 0, otherwise d1 is 1.
;
; Returns with: d0 error, 0=noErr
; a0 handle if no error
;
; Try temp memory if multifinder exists
;
move.l d0, -(sp) ;save requested size
moveq #0, d1 ;assume temp memory
_NewTempHandle ; look for it in temp memory
cmp.l (sp),d0 ;is it the size we requested?
beq.s @GotMem ;yes, it's big enough
_DisposeTempBuffer ;A0 already has handle of wrong size
;
; Try sys memory
;
@noMF
moveq #1, d1 ;not temp memory
move.l (sp),d0
_NewHandle ,sys
beq.s @GotMem
;
; Try app memory if zone different from system zone
;
move.l theZone,d0
cmp.l sysZone, d0 ;have we already tried this zone?
beq.s @Memoryerr ;don't try it again
move.l (sp),d0
_NewHandle
bne.s @MemoryErr ;couldn't find the memory anywhere
@GotMem
moveq #0,d0 ;signal noErr
@MemoryErr
addq #4,sp ;remove requested memory size
tst.w d0 ;set condition codes
rts
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Quickerdraw traps 380, 381, 384
;
;=========================================================================================
;=========================================================================================
FillClipScanLine PROC EXPORT
EXPORT FillClipOrLine, FillClipXLine
;---------------------------------------------------------
;
; INTERFACE TO EACH SCAN LINE ROUTINE:
;
; ENTER WITH Z-FLAG SET IF ALL IN ONE LONG
;
; INPUTS: A1: DSTPTR
; A2: MASKPTR
; D1: RIGHTMASK
; D2: LONGCNT
; D3: LEFTMASK
; D4: FGCOLOR
; D5: BKCOLOR
; D6: PATTERN
;
; CLOBBERS: D0,D3,D2,A1,A2
; A3,D6 (BUT NOT IN FASTSLAB)
;
ciROM384 EQU $2F230
ciOld381 EQU $2F1E6 ;<38> <6/30/90 DDG> corrected the return point for $AB81.
&CurFile SETC 'DRAWSLAB'
INCLUDE 'DrawingVars.a'
ALIGN Alignment
;******************************************************************************************
; QuickerDraw
; Scan line handler for clipped pattern fill copy mode (called by oval, rrect) -- trap $380
FCSL1 ; << PB452 BAL>>
FCSL2
slMASK8
AND.L (A2)+,D3 ;use left mask to start with
SUBQ #1,D2
BMI.S DoFCLast0
; special case the left edge
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
MOVE.L (A2)+,D3
SUBQ #1,D2
BMI.S DoFCLast0
; see if we're in the unclipped case; if so, use a faster loop
MOVE.L SEEKMASK(A6),A0 ;get seekRgn address
; CMP.W #$4E75,(A0) ;is it a RTS?
CMP.L #$343C7fff,(A0) ;is it "move.w #$7fff,d2"
BEQ.S DoFCUnclipped ;if so, handle specially
BRA.S FCNotOn1
; here's the loop -- use standard technique of special casing region masks
FCLineLoop
MOVE.L (A2)+,D3 ;fetch region mask
BEQ.S FCOff ;if all zero, can optimize
FCNotOff1
CMP.L MINUSONE,D3 ;all ones? << PB452 BAL>>
BEQ.S FCOn ;if so, optimize
FCNotOn1
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
DBRA D2,FCLineLoop
; handle the last one, using the mask in D1
DoFCLast
MOVE.L (A2)+,D3
DoFCLast0
AND.L D1,D3 ;use right mask
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
RTS
; handle the case of an all zero region mask
FCOff
ADDQ #4,A1 ;skip over it
SUBQ #1,D2
BMI.S DoFCLast
FCOffLoop
MOVE.L (A2)+,D3
BNE.S FCNotOff1
ADDQ #4,A1 ;skip it
DBRA D2,FCOffLoop
BRA.S DoFCLast
; handle the case of an all one's region mask
FCOn
MOVE.L D6,(A1)+
SUBQ #1,D2
BMI.S DoFCLast
FCOnLoop
MOVE.L (A2)+,D3
CMP.L MINUSONE,D3 ; << PB452 BAL>>
BNE.S FCNotOn1
MOVE.L D6,(A1)+
DBRA D2,FCOnLoop
BRA.S DoFCLast
; handle the unclipped case with faster unwound code
DoFCUnclipped
LEA 0(A2,D2.W*4),A2 ;bump region ptr
ADDQ #1,D2 ;compute count to do
CMP.W #8,D2
BLT.S FinishFCUnClip
MOVE.W D2,D0
LSR #3,D0 ;divide by 8
SUBQ #1,D0 ;bias for DBRA
FCUnClipLoop
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
DBRA D0,FCUnClipLoop
; now finish up the last 7 or less
FinishFCUnClip
AND #7,D2
EOR #7,D2
JMP FinishFCUCTab(D2.W*2)
FinishFCUCTab
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
MOVE.L D6,(A1)+
BRA.S DoFCLast
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 9 OR 13: PATTERN OR DST --> DST
;
;END9 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
;NEXT9 AND.L D6,D3 ;MASK PATTERN DATA
; AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
; MOVE.L D3,D0 ;COPY MASKED, CLIPPED SRC
; AND.L D4,D0 ;APPLY FG COLOR TO SRC
; NOT.L D3 ;GET NOT MASKED, CLIPPED SRC
; AND.L (A1),D3 ;USE TO PUNCH OUT DST
; OR.L D3,D0 ;COMBINE SRC AND DST
; MOVE.L D0,(A1)+ ;MOVE RESULT INTO DST
; MOVEQ #-1,D3 ;FLUSH MASK
; SUB #1,D2 ;DEC LONG COUNT
oldslMASK9
jmpROM ciOld381
; BGT NEXT9 ;LOOP FOR ALL LONGS IN ROW
; BEQ END9 ;DO LAST LONG WITH MASK
; RTS
;******************************************************************************************
; QuickerDraw
; Scan line handler for clipped pattern fill OR mode (called by oval, rrect) -- trap $381
; similar to above, but in OR mode. We can only handle if the foreground pattern
; is all ones; if so, use the copy mode routine to fill.
UseOld381
TST.W D2
bra.s oldslMASK9
FillClipOrLine
slMASK9
CMP.L #-1,D6 ;all foreground?
BNE.S UseOld381 ;if not, we can't handle
MOVE.L D4,D6 ;set up fill pattern
BRA slMASK8 ;use common code
;******************************************************************************************
ALIGN Alignment
;-------------------------------------------------------
;
; MODE 8 OR 12: BIG PATTERN --> DST
;
slXMASK8big
jmpROM ciROM384
; MOVE D7,-(SP) ;SAVE WORK REGISTER
; MOVE PATHMASK(A6),D7 ;GET HORIZ MASK
; MOVE D0,D6 ;GET LEFT AS INDEX INTO PATTERN
; ADD PATHPOS(A6),D6 ;GET OFFSET FROM PATTERN BASE
; AND D7,D6 ;MASK INDEX INTO PATTERN
; MOVE.L EXPAT(A6),A3 ;GET PATTERN POINTER
; ADD.l PATVPOS(A6),A3 ;ADD VERT OFFSET INTO PATTERN <BAL 22Jan89>
; TST D2
; BRA.S XDO8
;XEND8 AND.L D1,D3 ;COMBINE RIGHT AND LEFT MASK
;XNEXT8 MOVE.L 0(A3,D6),D0 ;GET PATTERN DATA
; ADDQ #4,D6 ;BUMP PATTERN INDEX
; AND D7,D6 ;MASK INDEX INTO PATTERN
; AND.L (A2)+,D3 ;MERGE MASK AND CLIPRGN MASK
; AND.L D3,D0 ;MASK PATTERN DATA
; NOT.L D3 ;MAKE NOTMASK
; AND.L (A1),D3 ;AND NOTMASK WITH OLD DST
; OR.L D0,D3 ;FILL HOLE WITH PATTERN
; MOVE.L D3,(A1)+ ;UPDATE DST
; MOVEQ #-1,D3 ;FLUSH MASK
; SUB #1,D2 ;DEC LONG COUNT
;XDO8 BGT XNEXT8 ;LOOP FOR ALL LONGS IN ROW
; BEQ XEND8 ;DO LAST LONG WITH MASK
; MOVE (SP)+,D7 ;RESTORE WORK REGISTER
; RTS
;******************************************************************************************
; QuickerDraw
; Scan line handler for clipped pattern fill copy mode (called by oval, rrect)
; for complex patterns-- trap $384
FillClipXLine
slXMASK8
CMP.W #4,PATHMASK(A6) ;pattern too complex?
BGT.S slXMASK8big ;if so, don't handle
MOVE.L D7,-(SP) ;save work register
; keep the pattern in D6 and D7
ADD.W PATHPOS(A6),D0
AND #4,D0
MOVE.L EXPAT(A6),A0
ADD.l PATVPOS(A6),A0 ; <BAL 07Nov89>
MOVE.L 0(A0,D0),D6 ;get left pattern
EOR.W #4,D0
MOVE.L 0(A0,D0),D7 ;get right pattern
; fetch the leftmost region mask
MOVEQ #-1,D4 ;all ones for comparing
AND.L (A2)+,D3 ;use left mask to start with
SUBQ #1,D2
BMI.S DoFCXLast0
; special case the left edge
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
EXG.L D6,D7
MOVE.L (A2)+,D3
SUBQ #1,D2
BMI.S DoFCXLast0
; see if we're in the unclipped case; if so, use a faster loop
MOVE.L SEEKMASK(A6),A0 ;get seekRgn address
; CMP.W #$4E75,(A0) ;is it a RTS?
CMP.L #$343C7fff,(A0) ;is it "move.w #$7fff,d2"
BEQ.S DoFCXUnclipped ;if so, handle specially
BRA.S FCXNotOn1
; here's the loop -- use standard technique of special casing region masks
FCXLineLoop
MOVE.L (A2)+,D3 ;fetch region mask
BEQ.S FCXOff ;if all zero, can optimize
FCXNotOff1
CMP.L D4,D3 ;all ones?
BEQ.S FCXOn ;if so, optimize
FCXNotOn1
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
EXG.L D6,D7
DBRA D2,FCXLineLoop
; handle the last one, using the mask in D1
DoFCXLast
MOVE.L (A2)+,D3
DoFCXLast0
AND.L D1,D3 ;use right mask
MOVE.L D6,D0 ;get pattern
AND.L D3,D0 ;mask it
NOT.L D3 ;flip mask
AND.L (A1),D3 ;combine with source
OR.L D3,D0 ;form dest longword
MOVE.L D0,(A1)+ ;deposit it
MOVE.L (SP)+,D7 ;restore work reg
RTS
; handle the case of an all zero region mask
FCXOff
ADDQ #4,A1 ;skip over it
EXG D6,D7 ;swap pattern halves, even if skipping <79>
SUBQ #1,D2
BMI.S DoFCXLast
FCXOffLoop
MOVE.L (A2)+,D3
BNE.S FCXNotOff1
ADDQ #4,A1 ;skip it
EXG D6,D7 ;swap pattern halves, even if skipping <79>
DBRA D2,FCXOffLoop
BRA.S DoFCXLast
; handle the case of an all one's region mask
FCXOn
MOVE.L D6,(A1)+
EXG.L D6,D7
SUBQ #1,D2
BMI.S DoFCXLast
FCXOnLoop
MOVE.L (A2)+,D3
CMP.L D4,D3
BNE.S FCXNotOn1
MOVE.L D6,(A1)+
EXG.L D6,D7
DBRA D2,FCXOnLoop
BRA.S DoFCXLast
; handle the unclipped case with faster unwound code
DoFCXUnclipped
LEA 0(A2,D2.W*4),A2 ;bump region ptr
ADDQ #1,D2 ;compute count to do
CMP.W #8,D2
BLT.S FinishFCXUnClip
MOVE.W D2,D0
LSR #3,D0 ;divide by 8
SUBQ #1,D0 ;bias for DBRA
FCXUnClipLoop
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
DBRA D0,FCXUnClipLoop
; now finish up the last 7 or less
FinishFCXUnClip
AND #7,D2
EOR #7,D2
BTST #0,D2
BEQ.S @0
EXG.L D6,D7
@0
JMP FinishFCXUCTab(D2.W*2)
FinishFCXUCTab
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
MOVE.L D7,(A1)+
MOVE.L D6,(A1)+
EXG.L D6,D7
BRA DoFCXLast
ENDPROC
;******************************************************************************************
;=========================================================================================
;=========================================================================================
;
; Patch to DisposGDevice
;
;=========================================================================================
;=========================================================================================
newDisposGDevice PROC EXPORT
;-------------------------------------------------------------
;
; PROCEDURE DisposGDevice (GDH: GDHandle);
;
; disposes of the gDevice record and its handles
;
; if the device we're disposing is the same as LastTxGDevice,
; move MainGDevice to LastTxGDevice
move.l 4(sp), a1 ;ok to Trash a1
cmp.l LastTxGDevice, a1 ;handle we're disposing same as LastTxGDev?
bne.s @BackToROM
move.l MainDevice, LastTxGDevice ;yes, update LastTxGDevice
@BackToROM
BackToTrap oldDisposGDevice
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to stNoStack to try for 128K instead of 64K.
;
;=========================================================================================
;=========================================================================================
stNoStack PROC EXPORT
ciNoMem EQU $379D8
ciSHOW EQU $37942
cistNoStack EQU $37992
&CurFile SETC 'STRETCH'
INCLUDE 'DrawingVars.a'
tst.l StackFree(a6) ;did we run out of stack?
bpl.s SHOW ;no, just go home
clr.l StackFree(a6)
movem.l d0-d3/a0-a2,-(sp) ;save state
neg.l d0 ;<BAL and KON 14Feb90>
move.l d0,stackFree(a6) ;<BAL and KON 14Feb90>
tst.l stackHandle(a6) ;have we been here before?
bne.s @noMem ;yes, forget it.
moveq #4,d0 ;Get 128K
jmpROM cistNoStack
@noMem
jmpROM ciNoMem
SHOW
jmpROM ciSHOW
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Come-from Patch so quickPoly's, drawline, and drawarc support large rowbytes.
;
;=========================================================================================
;=========================================================================================
ciFastSlabMode EQU $30040
FromArc EQU $34AB2
FromLine EQU $29D42
FromPoly EQU $340A8
FastSlabMode PROC EXPORT
IMPORT TryLineArc, RAMFastSlabMode
;--------------------------------------------------------------------
;
; PROCEDURE FastSlabMode, Call when rect clipped and pattern black.
;
; INPUT: D2: MODE, CLOBBERED mode 0=black, 1=xor, 2=white
; OUTPUT: A4: MODECASE
;
&CurFile SETC 'DRAWPOLY'
INCLUDE 'DrawingVars.a'
cmpRA FromPoly, (sp)
bne.s TryLineArc
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;GET DST ROWBYTES
AND #nuRBMask,D0 ;CLEAR FLAG BITS
EXT.L D0 ;MAKE IT LONG
MOVE.L D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
ADD.L D2,D1 ;ADD HORIZ BYTE OFFSET
MOVE.L D1,DSTLEFT(A6) ;SAVE AS DSTLEFT
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
BRA RAMFastSlabMode
ENDPROC
TryLineArc PROC EXPORT
IMPORT TryLine, RAMFastSlabMode
&CurFile SETC 'DRAWARC'
INCLUDE 'DrawingVars.a'
cmpRA FromArc, (sp)
bne.s TryLine
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;GET DST ROWBYTES
AND #nuRBMask,D0 ;CLEAR FLAG BITS
EXT.L D0 ;MAKE IT LONG
MOVE.L D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
ADD.L D2,D1 ;ADD HORIZ BYTE OFFSET
MOVE.L D1,DSTLEFT(A6) ;SAVE AS DSTLEFT
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
BRA RAMFastSlabMode
ENDPROC
TryLine PROC EXPORT
IMPORT RAMFastSlabMode
&CurFile SETC 'DRAWLINE'
INCLUDE 'DrawingVars.a'
cmpRA FromLine, (sp)
bne.s ArcLinePolyBackToROM
MOVE MINRECT+TOP(A6),D1
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT MINV TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;get dst rowbytes
AND #nuRBMask,D0 ;clear off flag bits
MOVE D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
ADD.L D2,D1 ;ADD HORIZ BYTE OFFSET
MOVE.L D1,DSTLEFT(A6) ;SAVE AS DSTLEFT
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
ArcLinePolyBackToROM
BRA RAMFastSlabMode
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Come-from Patch so quickPoly's, drawline, and drawarc support large rowbytes.
;
;=========================================================================================
;=========================================================================================
ciGetSeek EQU $3AF40
GETSEEK PROC EXPORT
IMPORT TryArcOrLine
ciReturnPoly EQU $34086
FromPolys EQU $34058
;-------------------------------------------------
;
; GetSeek(RgnHandle1, RgnHandle2, ..., HandleCount.L);
;
; SET UP ADDRESS OF SEEK ROUTINE IN SEEKMASK(A6)
; SET UP ADDRESS OF EXPAND ROUTINE IN EXRTN(A6)
;
; CLOBBERS: A0-A3,D0-D4
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
; LINK DONE BY CALLER (STRETCHBITS, RGNBLT, ScaleBlt, DRAWLINE, DRAWARC, QuickPolys)
;
&CurFile SETC 'DRAWPOLY'
INCLUDE 'DrawingVars.a'
cmpRA FromPolys, (sp) ;check old return address
bne.s TryArcOrLine
addq #4,sp ;set stack up just like getSeek expects
jsrROM ciGetSeek
peaROM ciReturnPoly ;new return address
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;GET DST ROWBYTES
AND #nuRBMask,D0 ;CLEAR FLAG BITS
EXT.L D0 ;MAKE IT LONG
MOVE.L D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
rts
ENDPROC
TryArcOrLine PROC EXPORT
IMPORT TryArc
FromDrawLine EQU $29CEC
ciReturnLine EQU $29D18
&CurFile SETC 'DRAWLINE'
INCLUDE 'DrawingVars.a'
cmpRA FromDrawLine, (sp)
bne.s TryArc
addq #4,sp ;set stack up just like getSeek expects
jsrROM ciGetSeek
peaROM ciReturnLine
MOVE MINRECT+TOP(A6),D1
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT MINV TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;get dst rowbytes
AND #nuRBMask,D0 ;clear off flag bits
MOVE D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
rts
ENDPROC
TryArc PROC EXPORT
FromDrawArc EQU $34A4A
ciReturnArc EQU $34A78
&CurFile SETC 'DRAWARC'
INCLUDE 'DrawingVars.a'
cmpRA FromDrawArc, (sp)
bne.s JustDoIt
addq #4,sp ;set stack up just like getSeek expects
jsrROM ciGetSeek
peaROM ciReturnArc
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;GET DST ROWBYTES
AND #nuRBMask,D0 ;CLEAR FLAG BITS
EXT.L D0 ;MAKE IT LONG
MOVE.L D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
rts
JustDoIt
jmpROM ciGetSeek
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch PutDirectPMData
;
;=========================================================================================
;=========================================================================================
PutDirectPMData PROC EXPORT ;17Jun88 BAL
PackWords EQU $35D60
;------------------------------------------------------
;
; PROCEDURE PutDirectPMData (mySrc,myData: Ptr; oldRowBytes: INTEGER);
;
; Currently, only default packing is implemented and packType is ignored
;
PARAMSIZE EQU 10
MYSRC EQU PARAMSIZE+8-4 ;src pixmap pointer
MYDATA EQU MYSRC-4 ;data pointer
OLDROWBYTES EQU MYDATA-2 ;old row bytes
SRCPTR EQU -4 ;VAR POINTER TO SOURCE
DSTPTR EQU SRCPTR-4 ;VAR POINTER TO DST
SRCBUF EQU DSTPTR-4 ;PTR TO REARRANGED SRC <16Jun88 BAL>
PACKBUF EQU SRCBUF-4 ;POINTER TO PACKING BUFFER
SAVEDSP EQU PACKBUF-4 ;PRESERVE STACK POINTER
VARSIZE EQU SAVEDSP
LINK A6,#VARSIZE ;MAKE A STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE WORK REGISTERS
MOVE.L SP,SAVEDSP(A6) ;PRESERVE STACK POINTER
MOVE.L MYSRC(A6),A2 ;POINT TO (TRIMMED) BITMAP
MOVE.L MYDATA(A6),A3 ;POINT TO THE DATA
MOVE OLDROWBYTES(A6),D4 ;GET OLD ROWBYTES
MOVEQ #8,D6 ;GET USEFUL VALUE
MOVE BOUNDS+BOTTOM(A2),D7
SUB BOUNDS+TOP(A2),D7 ;HEIGHT := BOUNDS BOT - TOP
;----------------------------------------------------------------
;
; 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
;----------------------------------------------------------------
;
; Determine desired packing scheme:
;
; Type Depth(s) Description
; ---- -------- -----------
; 1 16/32 No packing; Save trimmed memory image
; 2 16 Pixel packing; RunLength by pixel size (PackWords)
; 3 32 Drop pad byte; Save RGB triples
; 4 32 Run packing; RunLength by component by scanline
;
MOVE ROWBYTES(A2),D5 ;GET ROWBYTES
AND #nuRBMask,D5 ;CLEAR OFF FLAG BITS
CMP D6,D5 ;IS NEWROW < 8 ?
BLT NoPacking ;YES, DON'T TRY TO PACK
cmp.w #2,packType(a2) ;is packing desired?
blt NoPacking ;no, don't pack
beq DropPadByte ;yes, just drop pad byte
cmp.w #3,packType(a2) ;RunLength 16 bit pixels?
beq PixelPacking ;yes, run length (16 bit) pixels
RunPacking
;----------------------------------------------------------------
;
; ALLOCATE PACKBUF ON THE STACK
;
SUB D5,SP ;GET SIZE OF SRCBUF <16Jun88 BAL>
MOVE.L SP,SRCBUF(A6) ;POINT TO SRCBUF <16Jun88 BAL>
SUB D5,SP ;GET SIZE OF PACKBUF <16Jun88 BAL>
MOVE D5,D0 ;GET ROWBYTES <16Jun88 BAL>
LSR #8,D0 ;COMPUTE RUNS OF 128 BYTES <12Jul88 BAL>
ADDQ #1,D0 ;ROUND UP <16Jun88 BAL>
ADD.L D0,D0 ;ROUND UP <12Jul88 BAL>
SUB D0,SP ;GET ROOM FOR PACK COUNTS <16Jun88 BAL>
MOVE.L SP,PACKBUF(A6) ;POINT TO PACKBUF
; ASSUME: PIXELSIZE = 32
; CMPSIZE = 8
; CMPCOUNT = 3,4
ADDQ #4,A3 ;POINT PAST END OF FIRST PIXEL
SUB CMPCOUNT(A2),A3 ;POINT TO FIRST CMP OF FIRST PIXEL
;----------------------------------------------------------------
;
; PACKED FORMAT = [BYTECOUNT][RLE:rrrr...gggg...bbbb] FOR EACH SCANLINE
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
BRA START4 ;GO TO LOOP START
MORE4
moveq #true32b,d0 ;switch to 32 bit addressing for source access <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
MOVE CMPCOUNT(A2),D0 ;GET CMPCOUNT FOR LOOP <16Jun88 BAL>>
SUBQ #1,D0 ;MAKE IT ZERO BASED
MOVE.L SRCBUF(A6),A0 ;POINT TO UNWINDING BUFFER
MOVE D5,D3 ;GET ROWBYTES
LSR #2,D3 ;GET PIXEL WIDTH @@@@@
SUBQ #1,D3 ;MAKE IT ZERO BASED
@NXTCMP MOVE.L A3,A4 ;PTR INTO THIS CMP OF FIRST PIXEL
ADDQ #1,A3 ;POINT AT NEXT CMP
MOVE D3,D6 ;GET ROWBYTES
@NXTPIX MOVE.B (A4),(A0)+ ;COPY COMPONENT
ADDQ #4,A4 ;BUMP TO NEXT PIXEL
DBRA D6,@NXTPIX
DBRA D0,@NXTCMP ; <16Jun88 BAL><
moveq #false32b,d0 ;switch back before calling PutPicProc <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
SUB CMPCOUNT(A2),A3 ;RESET A3 TO FIRSTCMP, FIRSTPIX
MOVE.L SRCBUF(A6),SRCPTR(A6) ;SRCPTR := ^SCANLINE DATA
MOVE.L PACKBUF(A6),A0
MOVE.L A0,DSTPTR(A6) ;DSTPTR := @PACKBUF
PEA SRCPTR(A6) ;PUSH VAR SRCPTR
PEA DSTPTR(A6) ;PUSH VAR DSTPTR
ADDQ #1,D3 ;MAKE IT ONE BASED <16Jun88 BAL>
MULU CMPCOUNT(A2),D3 ;COMPUTE SIZE OF SRCBUF DATA <16Jun88 BAL>
MOVE D3,-(SP) ;PUSH SRCBYTES = NEWROW <16Jun88 BAL>
_PackBits ;PACK ROW INTO PACKBUF
MOVE.L DSTPTR(A6),D6 ;GET UPDATED DSTPTR
MOVE.L PACKBUF(A6),A0 ;POINT TO PACKBUF
SUB.L A0,D6 ;CALC PACKED BYTECOUNT
CMP #250,D5 ;IS ROWBYTES > 250?
BGT.S @1 ;=>YES, PUT WORD
MOVE.B D6,-(SP) ;ELSE PUSH THE BYTE
JSRROM PUTPICBYTE ;AND PUT TO PICTURE
BRA.S @2 ;=>AND GO PUT DATA
@1 MOVE.W D6,-(SP) ;PUSH PACKED BYTECOUNT
JSRROM PUTPICWORD ;PUT THE WORD
@2 MOVE.L PACKBUF(A6),-(SP)
MOVE D6,-(SP)
JSRROM PutPicData ;PUT PACKED DATA TO THEPIC
ADD D4,A3 ;ADD OLDROW TO BITS PTR
START4 DBRA D7,MORE4 ;LOOP FOR HEIGHT ROWS
BRA DONE ;ALL DONEROO
PixelPacking
;----------------------------------------------------------------
;
; ASSUME: PIXELSIZE = 16
;
; D4 = Src rowBytes
; D5 = Dst rowBytes
; D7 = Height
; A3 = Src Ptr
;
;----------------------------------------------------------------
;----------------------------------------------------------------
;
; ALLOCATE PACKBUF ON THE STACK
;
SUB D5,SP ;SET SIZE OF PACKBUF
SUB D5,SP ;TO 2*ROWBYTES FOR LONG ALIGNMENT
MOVE.L SP,PACKBUF(A6) ;POINT TO PACKBUF
;----------------------------------------------------------------
;
; PACKED FORMAT = [BYTECOUNT][DATA] FOR EACH SCANLINE
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
BRA.S START3 ;GO TO LOOP START
MORE3 MOVE.L A3,SRCPTR(A6) ;SRCPTR := ^SCANLINE DATA
MOVE.L PACKBUF(A6),A0
MOVE.L A0,DSTPTR(A6) ;DSTPTR := @PACKBUF
PEA SRCPTR(A6) ;PUSH VAR SRCPTR
PEA DSTPTR(A6) ;PUSH VAR DSTPTR
MOVE D5,-(SP) ;PUSH SRCBYTES = NEWROW
moveq #true32b,d0 ;switch to 32 bit addressing for source access <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
JSRROM PackWords ;PACK ROW INTO PACKBUF
moveq #false32b,d0 ;switch back before calling PutPicProc <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
MOVE.L DSTPTR(A6),D6 ;GET UPDATED DSTPTR
MOVE.L PACKBUF(A6),A0 ;POINT TO PACKBUF
SUB.L A0,D6 ;CALC PACKED BYTECOUNT
CMP #250,D5 ;IS ROWBYTES > 250?
BGT.S @1 ;=>YES, PUT WORD
MOVE.B D6,-(SP) ;ELSE PUSH THE BYTE
JSRROM PUTPICBYTE ;AND PUT TO PICTURE
BRA.S @2 ;=>AND GO PUT DATA
@1 MOVE.W D6,-(SP) ;PUSH PACKED BYTECOUNT
JSRROM PUTPICWORD ;PUT THE WORD
@2 MOVE.L PACKBUF(A6),-(SP)
MOVE D6,-(SP)
JSRROM PutPicData ;PUT PACKED DATA TO THEPIC
ADD D4,A3 ;ADD OLDROW TO BITS PTR
START3 DBRA D7,MORE3 ;LOOP FOR HEIGHT ROWS
BRA DONE ;ALL DONEROO
DropPadByte
;----------------------------------------------------------------
;
; ASSUME: PIXELSIZE = 32
; CMPSIZE = 8
; CMPCOUNT = 3
;
; D4 = Src rowBytes
; D5 = Dst rowBytes
; D7 = Height
; A3 = Src Ptr
;
;----------------------------------------------------------------
;
; ALLOCATE PACKBUF ON THE STACK
;
SUB D5,SP ;GET SIZE OF SRCBUF
MOVE.L SP,SRCBUF(A6) ;POINT TO SRCBUF
;----------------------------------------------------------------
;
; PACKED FORMAT = [BYTECOUNT][RGB,RGB,RGB,...] FOR EACH SCANLINE
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
MOVE D5,D6 ;GET ROWBYTES
LSR #2,D6 ;GET PIXEL WIDTH @@@@@
SUBQ #1,D6 ;MAKE IT ZERO BASED
;D6 has rowPixels-1
BRA.S START2 ;GO TO LOOP START
MORE2
moveq #true32b,d0 ;switch to 32 bit addressing for source access <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
MOVE.L SRCBUF(A6),A2 ;POINT TO UNWINDING BUFFER
MOVE.L A3,A4 ;PTR TO FIRST CMP OF FIRST PIXEL
move.w d6,d0 ;get rowPixels-1 in d0
@NXTPIX ADDQ #1,A4 ;POINT AT FIRST CMP (skip pad)
MOVE.B (A4)+,(A2)+ ;COPY red COMPONENT
MOVE.B (A4)+,(A2)+ ;COPY green COMPONENT
MOVE.B (A4)+,(A2)+ ;COPY blue COMPONENT
DBRA D0,@NXTPIX
moveq #false32b,d0 ;switch back before calling PutPicProc <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
SUB.L SRCBUF(A6),A2 ;CALC PACKED BYTECOUNT
@2 MOVE.L SRCBUF(A6),-(SP)
MOVE A2,-(SP)
JSRROM PutPicData ;PUT PACKED DATA TO THEPIC
ADD D4,A3 ;ADD OLDROW TO BITS PTR
START2 DBRA D7,MORE2 ;LOOP FOR HEIGHT ROWS
BRA.S DONE ;ALL DONEROO
NoPacking
;----------------------------------------------------------------
;
; ROWBYTES < 8, or PackType->noPacking, DONT USE PACKBITS
;
;
; D4 = Src rowBytes
; D5 = Dst rowBytes
; D7 = Height
; A3 = Src Ptr
;
;----------------------------------------------------------------
;
; ALLOCATE PACKBUF ON THE STACK
;
SUB D5,SP ;GET SIZE OF SRCBUF
MOVE.L SP,SRCBUF(A6) ;POINT TO SRCBUF
;----------------------------------------------------------------
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
ext.l d5 ;D5 has rowbytes
BRA.S START1 ;GO TO LOOP START
MORE1
moveq #true32b,d0 ;switch to 32 bit addressing for source access <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
MOVE.L SRCBUF(A6),A1 ;POINT TO dest BUFFER
MOVE.L A3,A0 ;PTR TO FIRST byte of src
move.l d5,d0 ;get rowbytes in d0
_BlockMove ;copy from there to here
;assumes here is a 24 bit address
moveq #false32b,d0 ;switch back before calling PutPicProc <BAL 02Feb90>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
MOVE.L SRCBUF(A6),-(SP)
MOVE D5,-(SP)
JSRROM PutPicData ;PUT PACKED DATA TO THEPIC
ADD D4,A3 ;ADD OLDROW TO BITS PTR
START1 DBRA D7,MORE1 ;LOOP FOR HEIGHT ROWS
DONE MOVE.L SAVEDSP(A6),SP ;RESTORE STACK POINTER
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'PUTDPMDAT' ;UNLINK AND RETURN
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to ScrollRect so the update region is set properly when scrolling between
; different resolution devices.
;
;=========================================================================================
;=========================================================================================
ScrollRect PROC EXPORT
ciScrollEntry EQU $35C1A
ciAbort EQU $35C3E
;---------------------------------------------------------------------
;
; PROCEDURE ScrollRect(srcRect: Rect; dh,dv: INTEGER; updateRgn: RgnHandle);
;
; Scroll a rectangular block of bits, erase and return an update region
; If the update region is nil, don't erase it.
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE EQU 12 ;TOTAL BYTES OF PARAMS
SRCRECT EQU PARAMSIZE+8-4 ;LONG, ADDR OF RECT
DH EQU SRCRECT-2 ;WORD
DV EQU DH-2 ;WORD
UPDATEREGION EQU DV-4 ;LONG, RGNHANDLE
DSTRECT EQU -8 ;RECT
tempRect1 EQU DSTRECT-8 ;rect
tempRect2 EQU tempRect1-8 ;rect
globalSrc EQU tempRect2-8 ;rect
VARSIZE EQU globalSrc ;TOTAL LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D6-D7/A3-A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
MOVE.L PICSAVE(A3),-(SP) ;SAVE PICSAVE HANDLE
CLR.L PICSAVE(A3) ;DON'T RECORD TO PICTURES
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT ABORT ;YES, QUIT FAST
TST.L DV(A6) ;ARE DH AND DV BOTH 0 ?
BEQ ABORT ;YES, QUIT FAST
; SAVE FOREGROUND AND BACKGROUND COLORS, AND SET TO BLACK AND WHITE FOR SCROLL
sub.l #ColorSpecSize,sp ;make room for an ColorSpec <DDG 28Jan90>
move.l sp,-(sp) ;point to this record
_SaveFore
sub.l #ColorSpecSize,sp ;make room for an ColorSpec <DDG 28Jan90>
move.l sp,-(sp) ;point to this record
_SaveBack
MOVE.L #BLACKCOLOR,-(SP) ;PUSH BLACK
_FORECOLOR ;AND SET FOREGROUND COLOR TO BLACK
MOVE.L #WHITECOLOR,-(SP) ;PUSH WHITE
_BACKCOLOR ;AND SET BACKGROUND COLOR TO BLACK
; ALLOCATE TEMP REGIONS FOR CALCULATIONS
SUB #8,SP ;ROOM FOR 2 FCN RESULT
_NEWRGN ;ALLOCATE SRCRGN
MOVE.L (SP)+,D7 ;GET SRCRGN IN D7
_NEWRGN ;ALLOCATE DSTRGN
MOVE.L (SP)+,D6 ;GET DSTRGN IN D6
; srcRgn := srcRect SECT visRgn SECT clipRgn
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
_RECTRGN ;RectRgn(srcRgn,srcRect);
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN
MOVE.L D7,-(SP) ;PUSH SRCRGN
_SECTRGN ;SectRgn(srcRgn,visRgn,srcRgn);
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN
MOVE.L D7,-(SP) ;PUSH SRCRGN
_SECTRGN ;SectRgn(srcRgn,clipRgn,srcRgn);
; dstRgn := offset srcRgn
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L D6,-(SP) ;PUSH DSTRGN
_COPYRGN ;CopyRgn(srcRgn,dstRgn);
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L DV(A6),-(SP) ;PUSH DH,DV
_OFSETRGN ;OffsetRgn(dstRgn,dh,dv);
; DSTRECT := OFFSETRECT(SRCRECT,DH,DV)
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE.L (A0)+,DSTRECT(A6) ;COPY SRCRECT INTO DSTRECT
MOVE.L (A0)+,DSTRECT+4(A6)
MOVE.L DV(A6),D0 ;GET DH,DV
ADD D0,DSTRECT+LEFT(A6) ;OFFSET DSTRECT (DH,DV)
ADD D0,DSTRECT+RIGHT(A6)
SWAP D0 ;GET DV IN LO WORD
ADD D0,DSTRECT+TOP(A6)
ADD D0,DSTRECT+BOTTOM(A6)
; MASKRGN := SECTRGN(SRCRGN,DSTRGN)
; NOTE: UPDATERGN CAN'T BE USED AS MASKRGN BECAUSE IF UPDATERGN = VISRGN
; THEN NOTHING WILL BE SCROLLED
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L D6,-(SP) ;KEEP MASKRGN
_SECTRGN ;SectRgn(srcRgn,dstRgn,maskRgn);
;----------------------------------------------------------------------------------------------------
;
; Now we check for multiple devices and do the correct things here <DDG 28Jan90>
;
move.l DeviceList,a0 ;get the head of the device list <DDG 28Jan90>
move.l (a0),a0 ;deref it
move.l GDNextGD(a0),d0 ;check the next device field. If it's zero
beq oneDevice ;..then goto one device
;
; Allocate extra region used by cutOutDevices
;
movem.l d5/a2,-(sp) ;save reg.
clr.l -(sp) ;make room for result
_NewRgn ;allocate another RGN <DDG 28Jan90>
move.l (sp)+,d5 ;put our new region in d5
;
; convert the source rect to global coordinates
;
move.l srcRect(a6),a1 ;point to our source rect
lea globalSrc(a6),a0 ;point to out global source rect
move.l (a1)+,topleft(a0) ;copy srcRect.topleft
move.l (a1)+,botright(a0) ;copy srcRect.botRight
pea topleft(a0) ;convert the global rect to global coordinates
_LocalToGlobal
pea botright(a0)
_LocalToGlobal
;
; Start scanning through the device list
;
move.l DeviceList,a2 ;get the device list header into A2
@loop move.l (a2),a4 ;deref the current device list handle
tst GDFlags(a4) ;is the device active ?
bpl.s @next ;=>no, skip to the next device
clr.b -(sp) ;make space for boolean result
pea globalSrc(a6) ;pointer to the SrcRect in global coordinates
pea GDRect(a4) ;pointer to the device rect
pea tempRect1(a6) ;pointer to the result
_SectRect ;get the intersection
tst.b (sp)+ ;if they didn't intersect at all, then skip to
beq.s @next ;..the next device
move.l DV(a6),d0 ;get DV into high word and DH into low word
add d0,tempRect1+left(a6)
add d0,tempRect1+right(a6)
swap d0 ;get DV into the low word
add d0,tempRect1+top(a6)
add d0,tempRect1+bottom(a6)
move.l GDPMap(a4),a0 ;get handle to the source pixMap
move.l (a0),a0 ;deref it
move.l pmTable(a0),a0 ;get handle to source color table
move.l (a0),a0 ;deref it
move.l ctSeed(a0),d1 ;get color table seed into d1
bsr cutOutDevices ;this cuts out different devices from d5
@next move.l (a2),a4 ;deref the current device list handle
move.l GDNextGD(a4),d0 ;get the next device handle into D0
move.l d0,a2 ;move it to our current handle. If it's NOT null
bne.s @loop ;..then loop back.
MOVE.L D5,A0 ;GET tmp region used by cutOutDevices
_DISPOSHANDLE ;DISCARD IT
movem.l (sp)+,d5/a2 ;restore d5
;----------------------------------------------------------------------------------------------------
oneDevice
; Scroll the rect using CopyBits
PEA PORTBITS(A3) ;PUSH SRCBITS
MOVE.L (SP),-(SP) ;PUSH DSTBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
PEA DSTRECT(A6) ;PUSH DSTRECT
CLR -(SP) ;PUSH MODE = SRCCOPY
MOVE.L D6,-(SP) ;PUSH MASK REGION
_COPYBITS ;COPY THE BITS
; RESTORE FOREGROUND AND BACKGROUND COLORS
move.l sp,-(sp) ;point to the saved back color and restore it
_RestoreBack ; <DDG 28Jan90>
add.l #ColorSpecSize,sp ;strip the ColorSpec off the stack
move.l sp,-(sp) ;point to the saved back color and restore it
_RestoreFore
add.l #ColorSpecSize,sp ;strip the ColorSpec off the stack
jmpROM ciScrollEntry
ABORT
jmpROM ciAbort
;----------------------------------------------------------------------------------------------------
cutOutDevices
move.l DeviceList,a1 ;get the device list header into A1
@loop move.l (a1),a0 ;deref the current device list handle
tst GDFlags(a0) ;is the device active ?
bpl @next ;=>no, skip to the next device
move.l GDPMap(a0),a0 ;get handle to the source pixMap
move.l (a0),a0 ;deref it
move.l pmTable(a0),a0 ;get handle to source color table
move.l (a0),a0 ;deref it
cmp.l ctSeed(a0),d1 ;do the color tables seeds match ?
beq.s @next
movem.l d1/a1,-(sp) ;save our scratch registers
clr.b -(sp) ;make space for boolean result
pea tempRect1(a6) ;pointer to the SrcRect in global coordinates
move.l (a1),a0 ;deref the current device list handle
pea GDRect(a0) ;pointer to the device rect
pea tempRect2(a6) ;pointer to the result
_SectRect ;get the intersection
tst.b (sp)+ ;if they didn't intersect at all, then skip to
beq.s @skip ;..the next device
lea tempRect2(a6),a0 ;point to our temp rect
pea topleft(a0) ;convert the temp rect back to local coordinates
_GlobalToLocal
pea botright(a0)
_GlobalToLocal
move.l d5,-(sp) ;convert tempRect2 into a region
pea tempRect2(a6)
_RectRgn
move.l d6,-(sp) ;subtract this little invalid rect out of the
move.l d5,-(sp) ;..mask region.
move.l d6,-(sp)
_DiffRgn
@skip movem.l (sp)+,d1/a1 ;restore our scratch registers
@next move.l (a1),a0 ;deref the current device list handle
move.l GDNextGD(a0),d0 ;get the next device handle into D0
move.l d0,a1 ;move it to our current handle. If it's NOT null
bne.s @loop ;..then loop back.
rts
ENDPROC
;----------------------------------------------------------------------------------------------------
;=========================================================================================
;=========================================================================================
;
; Patch to Index2Color to use the same algorithm as Search16toIndexed (stretch.a) in
; order to make colors match in SeedCFill/CalcCMask.
;
;=========================================================================================
;=========================================================================================
Index2Color PROC EXPORT
;
; procedure Index2Color ( index : longint; VAR myColor : RGBColor );
;
; This procedure takes an index value and returns the RGB
; components of this element of theGDPort^^.GDPMap.pmTable.
;
ciIndex2ColorEntry EQU $3C4DE
MOVE.L 8(SP),D0 ; get the index <C491/06Dec86> DAF
MOVE.L 4(SP),A0 ; get pointer to result RGB <C491/06Dec86> DAF
MOVE.L ([theGDevice]),A1 ; get the current device pointer
MOVE.L ([GDPMap,A1]),A1 ; get the device pixelmap pointer
cmp #16,pixelType(a1) ; is it a direct device? <BAL 06Jul88>
beq.s I2CDirect ; yes, no CLUT <BAL 06Jul88>
MOVE.L ([pmTable,A1]),A1 ; point to the color table
; CLR.W QDErr ; clear the error register <1.9>
MOVE.W ctSize(A1),D1 ; get ctSize <C491/06Dec86> DAF
CMP.W D1,D0 ; is index in range? <C491/06Dec86> DAF
BGT.S I2CErr ; nope, so quit <C491/06Dec86> DAF
MOVE.W CTTable+rgb+red(A1,D0.L*8),red(A0) ; move red <C491/06Dec86> DAF
MOVE.L CTTable+rgb+green(A1,D0.L*8),green(A0) ; move green & blue <C491/06Dec86> DAF
I2CDone
RTD #8 ; and return
I2CErr
MOVE.W #cRangeErr,QDErr ; set error code
BRA.S I2CDone ;
I2CDirect ; Handle 24bit/pixel direct devices <BAL 06Jul88>
moveq #8,d1 ; get handy constant
sub.w cmpSize(a1),d1 ; shift needed to left justify cmp
beq.s I2C24 ; cmpsize is 8 so go fast
;enter with a 16-bit source pixel in d0
lsl.l #3,d0 ;left align blue in lo byte
move.b d0,d1
lsl.l #5,d1 ;get 5 bits of blue
move.b d0,d1
lsl.l #5,d1 ;make into 10 bits of blue
move.b d0,d1
lsl.l #5,d1 ;make into 15 bits of blue
move.b d0,d1
lsr.l #7,d1 ;get a word of blue
MOVE.w d1,blue(a0) ;store out in color spec
lsr.l #5,d0 ;left align green in lo byte
move.b d0,d1
lsl.l #5,d1 ;get 5 bits of green
move.b d0,d1
lsl.l #5,d1 ;make into 10 bits of green
move.b d0,d1
lsl.l #5,d1 ;make into 15 bits of green
move.b d0,d1
lsr.l #7,d1 ;get a word of green
MOVE.w d1,green(a0) ;store out in color spec
lsr.l #5,d0 ;left align red in lo byte
move.b d0,d1
lsl.l #5,d1 ;get 5 bits of red
move.b d0,d1
lsl.l #5,d1 ;make into 10 bits of red
move.b d0,d1
lsl.l #5,d1 ;make into 15 bits of red
move.b d0,d1
lsr.l #7,d1 ;get a word of red
MOVE.w d1,red(a0) ;store out in color spec
bra.s I2CDone
I2C24
jmpROM ciIndex2ColorEntry
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to StdBits to clear dither bit when recording an old picture.
;
;=========================================================================================
;=========================================================================================
StdBits PROC EXPORT
IMPORT PutDirectPMData
;PutPMData EQU $336D0 defined earlier...
ciEntry EQU $3518E
ciNOTD EQU $351A6
ciNotPic EQU $351CE
ciBitsOK EQU $351CC
SHFTTBL EQU $304B6
;---------------------------------------------------------------
;
; PROCEDURE StdBits(VAR srcBits: BitMap;
; VAR srcRect: Rect;
; VAR dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle);
;
; SRC DEVICE RECORDS STORED ON STACK
FLAG EQU 0 ;OFFSET TO FLAG
DEV EQU FLAG+2 ;OFFSET TO DEVICE
RECT EQU DEV+4 ;OFFSET TO RECT
SIZE EQU RECT+8 ;SIZE OF RECORD
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 18
SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
SRCRECT EQU SRCBITS-4 ;LONG, ADDR OF RECT
DSTRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
SRCPIX EQU -(PMREC+CTREC+20) ;PIXMAP + COLOR TABLE
TEMPPIX EQU SRCPIX-PMREC ;PIXMAP
DSTBITS EQU TEMPPIX-4 ;DST BITMAP
GLOBALSRC EQU DSTBITS-8 ;GLOBAL COPY OF SRC RECT
GLOBALDST EQU GLOBALSRC-8 ;GLOBAL COPY OF DST RECT
SRCRECT1 EQU GLOBALDST-8 ;LOCAL COPY OF SRC RECT
DSTRECT1 EQU SRCRECT1-8 ;LOCAL COPY OF DST RECT (MUST FOLLOW SRCRECT1)
RECT1 EQU DSTRECT1-8 ;RESULT OF INTERSECTION
DEFSRC EQU RECT1-SIZE ;DEFAULT SRC RECORD
ENDSRC EQU DEFSRC-4 ;0 FOR TERMINATING SRC LIST
SRCDEV EQU ENDSRC-4 ;CURRENT SRC DEVICE RECORD
ENDDST EQU SRCDEV-4 ;0 FOR TERMINATING DST LIST
DSTDEV EQU ENDDST-4 ;CURRENT DST DEVICE
SRCLIST EQU DSTDEV-4 ;POINTER TO SORTED SRC RECT LIST
DSTLIST EQU SRCLIST-4 ;POINTER TO SORTED DST RECT LIST
SAVEDSP EQU DSTLIST-4 ;SAVED STACK POINTER
LASTSEED EQU SAVEDSP-4 ;LAST COLOR TABLE SEED
SAVEFG EQU LASTSEED-4 ;ORIGINAL FG COLOR
SAVEBK EQU SAVEFG-4 ;ORIGINAL BK COLOR
SAVEHILITE EQU SAVEBK-2 ;SAVED HILITE MODE FLAG
RGNA EQU SAVEHILITE-4 ;FIRST REGION FOR CLIPPING
RGNB EQU RGNA-4 ;SECOND REGION FOR CLIPPING
MASKBITS EQU RGNB-4 ;BITMAP FOR MASK
MASKRECT EQU MASKBITS-4 ;LONG, ADDR OF MASK RECT
isTmpHandle EQU MASKRECT-1 ;BYTE, FLAG SET IF temp memory used <1.5> BAL
OLDPIC EQU isTmpHandle-1 ;BYTE, FLAG SET IF OLD PICTURE <1.5> BAL
VARSIZE EQU OLDPIC ;TOTAL SIZE OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS
_CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE NOTPIC ;BRANCH IF NOT PICSAVE
;
; Set flag in OLDPIC(A6) if recording to old picture. <28May89 BAL>
;
MOVE.L PICSAVE(A3),A0 ;GET PICSAVE HANDLE <26May87 EHB>
MOVE.L (A0),A0 ;POINT TO PICSAVE RECORD <26May87 EHB>
CMP #PICTVERSION,PICVERSION(A0) ;IS IT AN OLD PICTURE? <26May87 EHB>
SEQ OLDPIC(A6) ;yes, set flag <26May87 EHB>
;----------------------------------------------------
;
; CONVERT SRCBITS TO A PIXMAP
; (A5 must contain global ptr)
;
MOVE.L SRCBITS(A6),A1 ;GET POINTER TO SRCBITS
TST ROWBYTES(A1) ;IS IT A BITMAP OR A PIXMAP
SPL D7 ;SET FLAG IF BITMAP
move d7,d6 ;Bits to pix clears pixmap/bitmap bit <30Jan90 KON>
or.b oldPic(a6),d7 ;d7=oldPic|bitMap <28May89 BAL>
LEA SRCPIX(A6),A2 ;COPY INTO SRCPIX
_BitsToPix ;BITMAP -> PIXMAP; RETURNS SCREEN FLAG IN D2 <BAL 19Sep88>
;----------------------------------------------------
;
; GET SHIFT AMOUNT FOR SRC DEPTH INTO D3
;
leaROM SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE SRCPIX+PIXELSIZE(A6),D0 ;GET SRC PIXEL SIZE
MOVEQ #0,D3 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D0),D3 ;GET SHIFT AMOUNT
;----------------------------------------------------
;
; IF SRC IS THE SCREEN, THEN USE COPYBITS TO COPY THE SRC TO AN OFFSCREEN BITMAP
; THIS ENSURES THAT SRC IS CONTIGUOUS, ALL ONE DEPTH, ETC.
;
CLR.L RECT1(A6) ;CLEAR HANDLE TO SAVED BITS
TST.B D2 ;IS SRC THE SCREEN? <BAL 19Sep88>
Bne.s doScreen ;Yes, convert it <KON 30Jan90>
tst.b d6 ;is source a bitmap? <KON 30Jan90>
bne notScrn ;YES, don't convert <KON 30Jan90>
tst.b OldPic(a6) ;is dst old port? <KON 30Jan90>
beq notScrn ;No, then don't convert source <KON 30Jan90>
bra doConvert
doScreen
IF 1 THEN ;Can't optimize if screen needs 32-bit addressing
;<d√b>
;----------------------------------------------------
; If the source is only one screen, copy straight across. (No need for
; temp offscreen pixmap.)
TST.B D7 ;Unless, that is, the dst is an OLD port,
BNE MultiMapSrc ;which'll require flattening.
MOVE.L SRCRECT(A6),A0 ;POINT TO SRC RECTANGLE
LEA SRCRECT1(A6),A1 ;POINT TO PLACE FOR COPY
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
PEA SRCRECT1(A6) ;PUSH COPY OF SRCRECT
NEG.W D1 ;left (D1=topLeft from BitsToPix)
SWAP D1
NEG.W D1 ;top
SWAP D1
MOVE.L D1,-(SP)
_OffsetRect ;SRCRECT1 is the global srcrect. (it used to happen later on)
CLR D4 ;How many devices does src intersect? <pb535a>
MOVE.L DeviceList,A2 ;A0=handle to head of device list
@gdrt
MOVE.L (A2),A2 ;A2->device
TST GDFLAGS(A2) ;IS IT ACTIVE?
BPL.S @nextgd ;=>NO, SKIP TO NEXT
SUBQ #2,SP ;Boolean result
PEA gdRect(A2) ;device global rect
PEA SRCRECT1(A6) ;source bitmap rect in global
PEA DSTRECT1(A6) ;put the intersection here(throwaway).
_SectRect
TST.B (SP)+ ;Any intersection at all?
BEQ.S @nextgd ;=>No, go do the next gd.
ADDQ #1,D4 ;=>Yes, count it. <pb535a>
MOVE.L A2,DSTDEV(A6) ;stash this device ptr here (as SRC)
@nextgd
MOVE.L gdNextGD(A2),D0
MOVE.L D0,A2
BNE.S @gdrt
CMP #1,D4 ;If the srcrect intersects more than <pb535a>
BGT.S MultiMapSrc ;one gdevice, do offscreen map.
MOVE.L DSTDEV(A6),A1 ;A1->the single source gdevice
MOVE.L gdPMap(A1),A1 ;A1=handle to pixmap
MOVE.L (A1),A1 ;A1->pixmap
move.l baseAddr(a1),d4 ;save un-stripped screen base in d4
LEA SRCPIX(A6),A2 ;A2->our local srcpix record
_BitsToPix ;BITMAP -> PIXMAP; RETURNS SCREEN FLAG IN D2
move.l d4,SRCPIX+baseAddr(a6) ;prevent stripping on alternate screens
PEA SRCPIX+bounds(A6) ;Fix bounds for SRCPIX
MOVE.L SRCBITS(A6),A0 ;by offsetting by original source bounds
MOVE.L bounds+topLeft(A0),-(SP)
_OffsetRect
leaROM SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE SRCPIX+PIXELSIZE(A6),D0 ;GET SRC PIXEL SIZE (redo for different gdevice)
MOVEQ #0,D3 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D0),D3 ;GET SHIFT AMOUNT (redo for different gdevice)
BRA NOTSCRN ;And pretend source isn't a screen.
MultiMapSrc ;2 or more active gdevices intersected
ENDIF
;----------------------------------------------------
;
; OFFSET SRCRECT TO GLOBAL COORDINATES AND GET SCREEN DEPTH
;
doConvert
MOVE.L SRCRECT(A6),A0 ;POINT TO SRC RECTANGLE
LEA SRCRECT1(A6),A1 ;POINT TO PLACE FOR COPY
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
PEA SRCRECT1(A6) ;PUSH COPY OF SRCRECT
MOVE.L SRCBITS(A6),A0 ;GET SRCBITS
MOVE.L BOUNDS(A0),D0 ;GET BOUNDS.TOPLEFT
NEG D0 ;NEGATE BOUNDS.LEFT
SWAP D0 ;GET BOUNDS.TOP
NEG D0 ;NEGATE BOUNDS.TOP
SWAP D0 ;GET BOUNDS.TOPLEFT
MOVE.L D0,-(SP) ;PUSH BOUNDS.TOPLEFT
_OFFSETRECT ;OFFSET RECT TO GLOBAL COORDINATES
CLR.L -(SP) ;MAKE ROOM FOR HANDLE
PEA SRCRECT1(A6) ;POINT TO GLOBAL RECT
_GETMAXDEVICE ;GET DEEPEST SCREEN DEVICE
MOVE.L (SP)+,D0 ;POP DEVICE HANDLE
BEQ BITSOK ;=>NOT ON SCREEN, DON'T RECORD
;----------------------------------------------------
;
; Set up off screen GDevice for the Copy
; SET TEMP PIXMAP USING INFO FROM DEEPEST SCREEN
;
move.l theGDevice,-(sp) ;save current GDevice <BAL 23Jan89>
move.l d0,theGDevice ;set up offscreen GDevice <BAL 23Jan89>
MOVE.L D0,A0 ;GET HANDLE TO DEEPEST DEVICE
MOVE.L (A0),A0 ;POINT TO DEEPEST DEVICE
MOVE.L GDPMAP(A0),A0 ;GET HANDLE TO ITS PIXMAP
MOVE.L (A0),A0 ;POINT TO PIXMAP
LEA TEMPPIX(A6),A1 ;POINT TO DST
MOVEQ #(PMREC/2)-1,D0 ;GET NUMBER OF WORDS IN RECORD
@0 MOVE (A0)+,(A1)+ ;COPY A WORD
DBRA D0,@0 ;=>REPEAT UNTIL DONE
clr.w TEMPPIX+PMVERSION(A6) ;clear 32bit addressing flag <BAL 15Dec88>
;----------------------------------------------------
;
; SET TEMPPIX.BOUNDS TO SRCRECT
;
MOVE.L SRCRECT(A6),A0 ;POINT AT SRC RECTANGLE
LEA TEMPPIX+BOUNDS(A6),A1 ;POINT AT DST BOUNDS
MOVE.L (A0)+,D1 ;GET TOPLEFT
MOVE.L D1,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,D0 ;GET BOTRIGHT
MOVE.L D0,(A1)+ ;COPY BOTRIGHT
MOVE D0,D5 ;GET A COPY OF RIGHT
SUB D1,D5 ;GET WIDTH IN PIXELS
EXT.L D5 ;MAKE IT LONG
;----------------------------------------------------
;
; FLAG IN D7 is set IF RECORDING A BITMAP or recording to old picture.
; GET DEPTH-SHIFT FOR PIXMAP IN D3 AND ROWBYTES FOR PICTURE IN D5.
; FORCE DEPTH TO 1 IF SRC IS BITMAP OR IF RECORDING OLD PICTURE.
;
MOVEQ #0,D3 ;DEFAULT SHIFT = 0
TST.B D7 ;IS IT A BITMAP? <BAL 28May89>
BNE.S ITSBITS ;=>YES, GO CALCULATE ROWBYTES
leaROM SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE TEMPPIX+PIXELSIZE(A6),D2 ;GET BITS PER PIXEL
MOVE.B 0(A0,D2),D3 ;GET SHIFT AMOUNT
ITSBITS LSL.L D3,D5 ;CONVERT PIXELS TO BITS
MOVEQ #15,D2 ;GET 15
ADD.L D2,D5 ;ROUND UP TO NEAREST WORD BOUNDARY
ASR.L #4,D5 ;DIV BY 16
BLE BITSOK ;IGNORE IF NEWROW <= 0
ADD D5,D5 ;DOUBLE FOR NEW ROWBYTES
MOVE D5,TEMPPIX+ROWBYTES(A6) ;COPY ROWBYTES
MOVE D5,D4 ;OLD ROWBYTES := NEW ROWBYTES
TST.B D7 ;IS DST A PIXMAP?
BNE.S NOFLAG ;=>NO, DON'T NEED FLAG
OR #$8000,TEMPPIX+ROWBYTES(A6) ;SET PIXMAP FLAG
NOFLAG
;----------------------------------------------------
;
; ALLOCATE MEMORY FOR TEMP PIXMAP AND COPY TO IT
;
SWAP D1 ;GET LEFTTOP
SWAP D0 ;GET RIGHTBOT
SUB D1,D0 ;GET HEIGHT
MULU D5,D0 ;GET DATA SIZE IN BYTES
move.l d0,d5 ;copy size in d5 <1.5> BAL
clr.b isTmpHandle(a6) ;clear temp memory flag <1.5> BAL
_NEWHANDLE ;ALLOCATE MEMORY FOR BITMAP
beq.s @gotMem ;go use it <1.5> BAL
st isTmpHandle(a6) ;set temp memory flag <1.5> BAL
move.l d5,d0 ;request size <1.5> BAL
_NewTempHandle ;ask for it <1.5> BAL
cmp.l d5,d0 ;did we get it all? <1.5> BAL
bge.s @gotMem ;yes, go use it <1.5> BAL
move.l (sp)+,theGDevice ;restore the current GDevice <1.5> BAL
move.w #-143,qdErr ;return something <1.5> BAL
bra BITSOK ;=>ERROR, JUST TRY TO DRAW <1.5> BAL
@gotMem MOVE.L A0,RECT1(A6) ;SAVE FOR DISPOSE
_HLOCK ;LOCK THE HANDLE
MOVE.L (A0),d0 ;POINT AT THE STORAGE
_rTranslate24To32 ;map address in D0 <02Feb90 BAL>
MOVE.L d0,TEMPPIX+BASEADDR(A6) ;AND SET BASE ADDRESS OF TEMP
MOVE.L PICSAVE(A3),-(SP) ;SAVE PICSAVE ON THE STACK
CLR.L PICSAVE(A3) ;DISABLE PICTURE FOR COPY!
SUBQ #6,SP ;MAKE ROOM FOR RGBCOLOR
MOVE.L SP,-(SP) ;POINT TO VAR RGBCOLOR
_GETFORECOLOR ;SAVE THE RGBFORECOLOR
MOVEQ #BLACKCOLOR,D0 ;GET A LITTLE BLACK
MOVE.L D0,-(SP) ;AND SMACK IT ON THE STACK
_FORECOLOR ;SO OUR COPY'S BACK IN WHACK
PEA SRCPIX(A6) ;PUSH TRIMMED SRC PIXMAP
PEA TEMPPIX(A6) ;PUSH DST PIXMAP
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L (SP),-(SP) ;DSTRECT = SRCRECT
CLR -(SP) ;MODE = SRC COPY
btst.b #6,Mode+1(a6) ;dither? <KON 30Jan90>
beq.s @NoDither ; <KON 30Jan90>
move.w #$40,(sp) ;set dither mode <KON 30Jan90>
@NoDither
CLR.L -(SP) ;NO MASKRGN
_COPYBITS ;COPY THE PIXMAP
MOVE.L SP,-(SP) ;POINT AT FORECOLOR
_RGBFORECOLOR ;RESTORE IT
ADDQ #6,SP ;STRIP FORECOLOR
MOVE.L (SP)+,PICSAVE(A3) ;RESTORE PICTURE STATE
move.l (sp)+,theGDevice ;restore the current GDevice <BAL 23Jan89>
;----------------------------------------------------
;
; COPY TEMPPIX INTO SRCPIX AND USE AS NEW SRC PIXMAP
;
LEA TEMPPIX(A6),A0 ;POINT TO TEMPPIX
LEA SRCPIX(A6),A1 ;POINT TO SRCPIX
MOVEQ #(PMREC/2)-1,D0 ;GET NUMBER OF WORDS IN PIXMAP
@0 MOVE (A0)+,(A1)+ ;COPY A WORD
DBRA D0,@0 ;=>REPEAT UNTIL DONE
NOTSCRN
;----------------------------------------------------
;
; TRIM LOCAL COPY OF PIXMAP
;
LEA SRCPIX(A6),A1 ;POINT TO PIXMAP
MOVE.L BASEADDR(A1),A3 ;GET BASEADDR
MOVE ROWBYTES(A1),D4 ;GET OLD ROWBYTES
AND #nuRBMask,D4 ;CLEAR FLAG BITS
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE TOP(A0),D0 ;GET SRCRECT.TOP
SUB BOUNDS+TOP(A1),D0 ;SKIPTOP:=SRCRECT.TOP-BOUNDS.TOP
BLE.S TOPOK ;CONTINUE IF SKIPTOP NEG
ADD D0,BOUNDS+TOP(A1) ;NEWTOP := SRCRECT TOP
MULU D4,D0 ;CALC VERT OFFSET
ADD.L D0,A3 ;ADJUST BASEADDR
TOPOK MOVE BOTTOM(A0),D0 ;GET SRCRECT.BOTTOM
CMP BOUNDS+BOTTOM(A1),D0 ;IS SRCRECT BOT < BOUNDS BOT ?
BGE.S BOTOK ;NO, CONTINUE
MOVE D0,BOUNDS+BOTTOM(A1) ;YES, TRIM BOUNDS BOTTOM
BOTOK MOVE LEFT(A0),D0 ;GET SRCRECT.LEFT
SUB BOUNDS+LEFT(A1),D0 ;CALC SKIPLEFT
BLE.S LEFTOK ;CONTINUE IF SKIPLEFT NEG
EXT.L D0 ;MAKE IT LONG
LSL.L D3,D0 ;CONVERT PIXELS TO BITS
ASR.L #3,D0 ;DIV BY 8 FOR SKIP BYTES
ADD.L D0,A3 ;OFFSET BASEADDR HORIZ
LSL.L #3,D0 ;BYTES TIMES 8 FOR BITS
ASR.L D3,D0 ;CONVERT BITS TO PIXELS
ADD D0,BOUNDS+LEFT(A1) ;ADD DOTS TO BOUNDS.LEFT
LEFTOK MOVE RIGHT(A0),D0 ;GET SRCRECT.RIGHT
SUB BOUNDS+LEFT(A1),D0 ;CONVERT TO GLOBAL
EXT.L D0 ;MAKE IT LONG
ADDQ.L #7,D0 ;ROUND UP
LSL.L D3,D0 ;CONVERT PIXELS TO BITS
AND #$FFF8,D0 ;TRUNC TO BYTE BOUNDARY
ASR.L D3,D0 ;CONVERT BITS TO PIXELS
ADD BOUNDS+LEFT(A1),D0 ;RETURN TO LOCAL
CMP BOUNDS+RIGHT(A1),D0 ;IS RESULT < BOUNDS.RIGHT ?
BGE.S RIGHTOK ;NO, CONTINUE
MOVE D0,BOUNDS+RIGHT(A1) ;YES, TRIM RIGHT
RIGHTOK
;
; CALC NEW ROWBYTES AFTER TRIMMING
;
MOVE BOUNDS+RIGHT(A1),D5 ;GET TRIMMED RIGHT
SUB BOUNDS+LEFT(A1),D5 ;CALC WIDTH IN PIXELS
EXT.L D5 ;MAKE IT LONG
LSL.L D3,D5 ;CONVERT PIXELS TO BITS
MOVEQ #15,D0 ;GET 15
ADD.L D0,D5 ;ROUND UP TO NEAREST WORD BOUNDARY
ASR.L #4,D5 ;DIV BY 16
BLE BITSOK ;IGNORE IF NEWROW <= 0
ADD D5,D5 ;DOUBLE FOR NEW ROWBYTES
MOVE D5,ROWBYTES(A1) ;COPY ROWBYTES
OR #$8000,ROWBYTES(A1) ;SET PIXMAP FLAG
clr.w SRCPIX+PMVERSION(A6) ;clear 32bit addressing flag <BAL 15Dec88>
;----------------------------------------------------
;
; PUT THE BITMAP TO THE PICTURE
;
MOVEQ #8,D6 ;GET A USEFUL NUMBER
MOVE #opBitsRect,-(SP) ;PUSH OPCODE=BITSRECT
TST.L MASKRGN(A6) ;IS MASKRGN NIL ?
BEQ.S NOTRGN ;YES, CONTINUE
ADD #1,(SP) ;REPLACE OPCODE=BITSRGN (IE. $91)
;FIXED BUG 12/3/83, RP
NOTRGN CMP D6,D5 ;IS NEWROW < 8 ?
Bge.s PACK ;YES, DONT BITPACK
move #1,SRCPIX+PACKTYPE(A6) ;replace with "UnPacked" packType
bra.s NoPack
PACK ADD #8,(SP) ;SET BIT 3 FOR BITPACK
NoPack TST.B D7 ;New Picture?
BNE.S OPOK ;=>NO, can't be direct data <BAL 01Mar89>
MOVE.W SRCPIX+pixelType(A6),D2 ;get pixelType in d2 for later %%%
cmp #16,D2 ;is it chunky direct? %%%
bne.s OPOK ;NO, OPCODE IS OK %%%
OR.W #$A,(SP) ;YES, USE $9A AND $9B %%%
jsrROM PutPicOp ;PUT OPCODE TO THEPIC %%%
MOVE.L #$0FF,-(SP) ;PUT HACK TO PIC %%%
jsrROM PutPicLong
lea srcPix+packType(a6),a0 ;point at packType
CMP #1,(a0) ;PACKING? <BAL 11Jul88>
beq.s @PackOK ;no, don't need to adjust packType <BAL 11Jul88>
CMP #16,SRCPIX+PIXELSIZE(A6) ;16 bit/pixel? <BAL 15Dec88>
bne.s @pack32 ;no, check 32 bit/pixel packing types <BAL 15Dec88>
move #3,(a0) ;use only supported type
bra.s @PackOK
@pack32 cmp #2,(a0) ;drop pad byte only? <BAL 11Jul88>
beq.s @PackOK ;yes, don't need to adjust packType <BAL 11Jul88>
move #4,(a0) ;replace with only remaining supported packType <BAL 15Dec88>
@PackOK MOVE SRCPIX+BOUNDS+BOTTOM(A6),D1 ; %%%
SUB SRCPIX+BOUNDS+TOP(A6),D1 ;HEIGHT := BOUNDS BOT - TOP %%%
MULU D1,D5 ;SAVE PMDATA SIZE IN D5 %%%
PEA SRCPIX+ROWBYTES(A6) ;PUSH ADDR OF PIXMAP %%%
MOVE #PMREC-4,-(SP) ;PUSH SIZE OF PIXMAP (-BASEADDR)
jsrROM PutPicData ;PUT PIXMAP TO THEPIC %%%
BRA.S NOTABLE ;SKIP CLUT STUFF %%%
OPOK jsrROM PutPicOp ;PUT OPCODE TO THEPIC
MOVEQ #PMREC-4,D0 ;GET SIZE OF PIXMAP (-BASEADDR)
TST.B D7 ;ARE WE RECORDING A BITMAP?
BEQ.S DOPM ;=>SRC IS PIXMAP, PUT PIXMAP
AND #nuRBMask,SRCPIX+ROWBYTES(A6) ;ELSE BITMAP, CLEAR FLAGS
MOVEQ #BITMAPREC-4,D0 ;GET SIZE OF BITMAP (-BASEADDR)
DOPM PEA SRCPIX+ROWBYTES(A6) ;PUSH ADDR OF BITMAP/PIXMAP
MOVE D0,-(SP) ;PUSH BYTECOUNT
jsrROM PutPicData ;PUT BITMAP/PIXMAP TO THEPIC
; IF IT'S A PIXMAP, PUT THE COLOR TABLE TO THE PICTURE
TST.B D7 ;IS IT A PIXMAP?
BNE.S NOTABLE ;=>NO, DON'T DO TABLE
MOVE.L SRCPIX+PMTABLE(A6),d0 ;get CTabHandle
beq.s PutMinimalTable ;Put min table if NIL <21> <KON 29NOV90>
move.l d0, -(SP) ;PUSH CTABHANDLE <20> <KON 30OCT90>
jsrROM PutPicTable ;ADD TABLE TO THEPIC
bra.s NoTable
;
; The following is a minimal color table. It is put to the picture if a PixMap has
; a NIL color table. <KON 29NOV90>
;
arithMode
;avg addPin addOver subPin trans max subOver min
DC.B srcCopy, srcBic, srcXor, srcOr, srcOr, srcBic, srcXor, srcOr
MinimalTable
dc.l 0 ;ctSeed
dc.w 0 ;flags
dc.w 0 ;0-based count of entries -> 1 entry
dc.w cTabSignature,0,0,0 ;ColorSpec for 1 entry with signature
MinTableSize EQU 16
;
; Put the minimal color table to the picture
;
PutMinimalTable
pea MinimalTable ;PUSH DATAPTR <KON 29NOV90>
move #MinTableSize,-(sp) ;GET SIZE IN ENTRIES <KON 29NOV90>
jsrROM PutPicData ;ADD TO THEPIC <KON 29NOV90>
NOTABLE MOVE.L SRCRECT(A6),-(SP)
MOVE D6,-(SP)
jsrROM PutPicData ;PUT SRCRECT
MOVE.L DSTRECT(A6),-(SP)
MOVE D6,-(SP)
jsrROM PutPicData ;PUT DSTRECT
MOVE MODE(A6),D0 ;get desired mode <26May87 EHB>
TST.B OLDPIC(A6) ;is it an old picture? <26May87 EHB>
BEQ.S @ModeOK ;=>no, mode is fine <26May87 EHB>
bclr #6,d0 ;don't record ditherCopy in old Picts
BTST #5,D0 ;an arithmetic mode? <26May87 EHB>
BEQ.S @ModeOK ;=>no, mode is fine <26May87 EHB>
AND #$07,D0 ;else strip to low 3 bits <26May87 EHB>
MOVE.B ARITHMODE(D0),D0 ;and remap it <26May87 EHB>
@ModeOK MOVE D0,-(SP) ;push mode <26May87 EHB>
jsrROM PutPicWord ;PUT MODE
TST.L MASKRGN(A6) ;IS MASKRGN NIL ?
BEQ.S NOMASK ;YES, SKIP IT
MOVE.L MASKRGN(A6),-(SP) ;NO, PUSH MASKRGN
jsrROM PutPicRgn ;PUT MASKRGN TO THEPIC
NOMASK tst.b d7 ;is it a pixmap ? If not, then <17Jan89 DDG>
bne.s @NOTD ;don't check pixmap fields ! <17Jan89 DDG>
cmp #16,SRCPIX+pixelType(A6) ;is it chunky direct? %%%
bne.s @NOTD ;NO, CALL PACKING STUFF %%%
LEA SRCPIX(A6),A0 ;GET PIXMAP POINTER
MOVE.L A0,-(SP) ;PUSH PIXMAP POINTER
MOVE.L A3,-(SP) ;PUSH ADJUSTED BASEADDR
MOVE D4,-(SP) ;PUSH OLD ROWBYTES
bsr PutDirectPMData ;AND PUT DATA TO PICTURE
BRA.S @DONE
@NOTD LEA SRCPIX(A6),A0 ;GET PIXMAP POINTER
MOVE.L A0,-(SP) ;PUSH PIXMAP POINTER
MOVE.L A3,-(SP) ;PUSH ADJUSTED BASEADDR
MOVE D4,-(SP) ;PUSH OLD ROWBYTES
jsrROM PutPMData ;AND PUT DATA TO PICTURE
@DONE MOVE.L RECT1(A6),D0 ;DID WE ALLOCATE DATA FOR A PIXMAP?
BEQ.S BITSOK ;=>NOPE, DON'T NEED TO DISPOSE
MOVE.L D0,A0 ;ELSE GET HANDLE
tst.b isTmpHandle(a6) ;is it from temp memory? <1.5> BAL
beq.s @notTmp ;no, dispose as usual <1.5> BAL
_DisposeTempBuffer ;yes, dispose as temp memory <1.5> BAL
bra.s BITSOK ; <1.5> BAL
@notTmp _DISPOSHANDLE ;AND DISPOSE OF IT
BITSOK MOVE.L THEPORT(A4),A3 ;RESTORE THEPORT
; CALL HEAVY-DUTY LOOP TO DRAW TO ALL DEVICES
NOTPIC TST PNVIS(A3) ;IS PNVIS >= 0 ?
BLT.S GOHOME ;NO, QUIT
LEA PORTBITS(A3),A0 ;GET DST BITMAP
MOVE.L A0,DSTBITS(A6) ;AND PLACE IN STACK FRAME
MOVE.L VISRGN(A3),RGNA(A6) ;PASS VISRGN
MOVE.L CLIPRGN(A3),RGNB(A6) ;AND CLIPRGN
CLR.L MASKBITS(A6) ;NO MASK BITMAP
CLR.L MASKRECT(A6) ;NO MASK RECTANGLE
_BitsDevLoop ;DRAW TO ALL DEVICES
GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDBITS '
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to make direct pixpats work in pictures
; Requires come-from on CopyPixPat and complete replacement of PutPicPixPat
;
;=========================================================================================
;=========================================================================================
COPYPIXPAT PROC EXPORT
IMPORT COPYPIXMAP,COPYHANDLE,PutPicPixPat
ciCopyPixPat EQU $30840
FromUpdatePat EQU $32EAE
ciUpdatePat EQU $32EBE
;-------------------------------------------------------------
;
; PROCEDURE COPYPIXPAT (SRCPP,DSTPP: PixPatHandle);
;
; COPY THE SRC PIXPAT'S DATA TO THE DST PIXPAT'S HANDLES
;
cmpRA FromUpdatePat,(sp)
beq.s @FoundIt
jmpROM ciCopyPixPat
@FoundIt
;
; Patch uses updatePat stack frame
;
PARAMSIZE EQU 20
SRCPAT EQU PARAMSIZE+8-4 ;PTR
SRCPIXPAT EQU SRCPAT-4 ;HANDLE
SAVEPAT EQU SRCPIXPAT-4 ;PTR
SAVEPIXPAT EQU SAVEPAT-4 ;HANDLE
OLDOP EQU SAVEPIXPAT-2 ;WORD
NEWOP EQU OLDOP-2 ;WORD
addq #4,sp ;delete old return address
jsrROM ciCopyPixPat ;call it and comeback here
MOVE NEWOP(A6),D0 ;GET PIXPAT OPCODE
jsrROM DPutPicOp ;ADD TO THEPIC
MOVE.L SAVEPIXPAT(A6),-(SP) ;PUSH NEW PAT
JSR PutPicPixPat ;AND PUT TO PICTURE
jmpROM ciUpdatePat
ENDPROC
PutPicPixPat PROC EXPORT
IMPORT PutDirectPMData
PutPicPixMap EQU $33030
;------------------------------------------------------
;
; PROCEDURE PutPicPixPat(PixPatHandle);
;
MOVE.L A2,-(SP) ;SAVE WORK REGISTER
MOVE.L 8(SP),A0 ;GET HANDLE TO PIXPAT
_HLock ;LOCK PIXPAT
MOVE.L (A0),A2 ;A2 = PIXPAT POINTER
MOVE.L patMap(A2),A0 ;GET PIXMAP HANDLE
MOVE.L (A0),A0 ;A1 = PIXMAP POINTER
; PUT TYPE AND ONE BIT PATTERN
MOVE patType(A2),-(SP) ;PUSH TYPE
jsrROM PutPicWord ;PUT TYPE TO THEPIC
MOVE.L pat1Data(A2),-(SP) ;PUSH 1ST HALF OF ONE BIT PATTERN
jsrROM PutPicLong ;PUT 1st HALF TO THEPIC
MOVE.L pat1Data+4(A2),-(SP) ;PUSH 2ND HALF OF ONE BIT PATTERN
jsrROM PutPicLong ;PUT 2ND HALF TO THEPIC
; IF IT IS A DITHERPAT, PUT RGB COLOR TO THE PICTURE (AND SKIP PIXMAP AND DATA)
CMP #ditherPat,patType(A2) ;IS IT A DITHER PATTERN?
BNE.S @PutMap ;=>NO, PUT PIXMAP
MOVE.L patMap(A2),A0 ;GET PATTERN'S PIXMAP
MOVE.L (A0),A0 ;POINT AT IT
MOVE.L PMTable(A0),A0 ;GET COLOR TABLE
MOVE.L (A0),A0 ;AND POINT AT IT
LEA CTTable+(4*CTEntrySize)(A0),A0 ;POINT TO RGB
MOVE rgb+blue(A0),-(SP) ;PUSH BLUE
MOVE.L rgb+red(A0),-(SP) ;PUSH RED, GREEN
jsrROM PutPicLong ;PUT RED, GREEN TO PICTURE
jsrROM PutPicWord ;PUT BLUE TO PICTURE
BRA @NoData ;=>DON'T NEED PIXMAP
; PUT PIXMAP TO THE PICTURE
@PutMap
MOVE.L patMap(A2),A1 ;GET PIXMAP HANDLE
MOVE.L (A1),A1 ;GET PIXMAP PTR
move.w packtype(a1),-(sp) ;save packtype <KON 4FEB90>
move.w pmVersion(a6),-(sp) ;save pmVersion <KON 4FEB90>
move.l a1,-(sp) ;PutPMData trashes A1 <KON 5APR91>
clr.w pmVersion(a6) ;only let version zero be stored in pict.
cmp #16,pixelType(A1) ;is it chunky direct?
bne.s @PackOK ;don't do special packing
lea packtype(a1),a0
cmp #1,(a0) ;PACKING?
beq.s @PackOK ;no, don't need to adjust packType
cmp #16,pixelsize(A1) ;16 bit/pixel?
bne.s @pack32 ;no, check 32 bit/pixel packing types
move #3,(a0) ;use only supported type
bra.s @PackOK
@pack32 cmp #2,(a0) ;drop pad byte only?
beq.s @PackOK ;yes, don't need to adjust packType
move #4,(a0) ;replace with only remaining supported packType
@PackOK
MOVE.L patMap(A2),-(SP) ;PUSH PIXMAP HANDLE FOR PUTPICPIXMAP
jsrROM PutPicPixMap ;ADD PIXMAP TO THEPIC
; PUT DATA TO PICTURE
MOVE.L patData(A2),A0 ;GET DATA HANDLE
_HLock ;LOCK DATA
MOVE.L patMap(A2),A1 ;GET PIXMAP HANDLE
MOVE.L (A1),A1 ;GET PIXMAP PTR
MOVE.L A1,-(SP) ;PUSH PIXMAP PTR
move.l (a0),d0
_rTranslate24To32 ;map address in D0 <02Feb90 BAL>
MOVE.L d0,-(SP) ;PUSH DATA PTR
MOVE ROWBYTES(A1),D0 ;GET ROWBYTES
AND #nuRBMask,D0 ;CLEAR FLAG BITS
MOVE D0,-(SP) ;PUSH SOURCE ROWBYTES
;
; if direct pixPat, call PutDirectPMData <KON 4FEB90>
;
cmp #16,pixelType(A1) ;is it chunky direct?
bne.s @NOTD ;NO, CALL PACKING STUFF
;
; Do direct case
;
bsr PutDirectPMData ;and put data to picture
bra.s @done
@NOTD
;
; Do indexed case
;
jsrROM PutPMData ;PUT DATA TO PICTURE
@DONE
move.l (sp)+,a1 ;restore a1 which was trashed by PutPMData <KON 5APR91>
move.w (sp)+,pmVersion(a6) ;restore pmVersion <KON 4FEB90>
move.w (sp)+,packtype(a1) ;restore packtype <KON 4FEB90>
MOVE.L patData(A2),A0 ;GET DATA HANDLE
_HUnlock ;UNLOCK DATA
; UNLOCK PIXPAT AND RETURN
@NoData MOVE.L 8(SP),A0 ;GET PIXPAT HANDLE
_HUnlock ;UNLOCK PIXPAT
MOVE.L (SP)+,A2 ;RESTORE WORK REGISTER
MOVE.L (SP)+,(SP) ;STRIP PARAM
RTS ;AND RETURN
ENDPROC
arithMode PROC EXPORT
; hilite
;avg addPin addOver subPin trans max subOver min
DC.B srcCopy, srcBic, srcXor, srcOr, srcOr, srcBic, srcXor, srcOr
;=========================================================================================
;=========================================================================================
;
; Patch to ColorMap to make 1-bit old copy mode work
;
;=========================================================================================
;=========================================================================================
ColorMap PROC EXPORT
IMPORT arithMode, NOPfgColorTable
ciDestBitMap EQU $2ED48
ciReMap2 EQU $2EDD6
ciColorOK EQU $2EE24
ciReMapReturn EQU $2EDAE
ciRep EQU $2EDBE
;----------------------------------------------------------------
;
; PROCEDURE ColorMap: (pat: Pattern; mode: INTEGER);
;
; ADJUST INPUT MODE AND PATTERN TO ACCOMPLISH COLOR SEPARATION.
; POTENTIALLY MODIFIES: LOCMODE, NEWPATTERN, LOCPAT, FCOLOR, BCOLOR.
;
; ADJUSTED MODE IS RETURNED IN LOCMODE(A6).
; IF PATTERN IS ADJUSTED, THEN NEWPATTERN(A6) IS SET FALSE AND LOCPAT(A6) IS MODIFIED.
; FCOLOR(A6) AND BCOLOR(A6) ARE MODIFIED AS DESCRIBED BELOW.
;
; IF OLD PORT, TRANSLATES OLD-STYLE FGCOLOR, BKCOLOR INTO AN RGB,
; AND THEN GETS THE INDEX FOR THAT COLOR. FOR ALL PORTS, THE
; RETURNED COLOR CONTAINS THE PIXEL REPLICATED THROUGHOUT THE LONG
; (SUITABLE FOR MASKING).
;
; FOR EITHER MODE, IF THE DESTINATION IS ONE BIT DEEP, DO PLANAR REMAPPING
; SO THAT FASTEST COPYBITS BLT ROUTINES DON'T NEED TO APPLY COLOR.
;
; CLOBBERS A0-A1,D0-D2
;
; CALLED BY: DRAWARC, DRAWLINE, STRETCH
; A6 STACK FRAME ALLOCATED BY CALLER, USED LOCALLY.
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
;
&CurFile SETC 'COLORMAP'
INCLUDE 'DrawingVars.a'
;-------------------------------------------------
PARAMSIZE EQU 0 ;SIZE OF PARAMETERS
VARSIZE EQU 0 ;SIZE OF LOCALS
; LINK A4,#VARSIZE ;MAKE A STACK FRAME
MOVEM.L D3-D7/A2-A3,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A2 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A2),A2 ;POINT TO THE PORT
MOVE locMode(A6),D3 ;get the mode
MOVE.L FGCOLOR(A2),D6 ;GET FOREGROUND COLOR INTO D6
MOVE.L BKCOLOR(A2),D7 ;GET BACKGROUND COLOR INTO D7
; <1.6> BAL
@modeOK MOVE D3,D1 ;make a copy of the mode
AND #$FFF7,D3 ;clear the pattern bit
EOR D3,D1 ;set only the pattern bit
CMP #srcXor,D3 ;could it be replaced by hilite?
BNE.S @noXorSub
BSET #hiliteBit,HiliteMode ;check to see if highlight bit was set
BNE.S @noXorSub ;if not, invert old way
MOVE #$32,D3 ;set to src highlight
@noXorSub
BTST #5,D3 ;an arithmetic mode?
BEQ.S @leaveModeAlone ;skip if no mode
CMP #1,dstPix+pixelSize(A6) ;1 bit per pixel on the destination
BNE.S @leaveModeAlone
AND #$07,D3 ;get variants
MOVE.B arithMode(D3),D3 ;get mapped mode in 1 bit
@leaveModeAlone
OR D1,D3 ;combine mapped mode and pattern bit
MOVE D3,locMode(A6) ;save off altered mode
CLR.B alphaMode(A6) ;clear the alpha mode to default
BTST #5,D3 ;check again for arithmetic modes
BNE @noalpha ;skip alpha stuff if arithmetic
MOVE.W dstShift(A6),D0 ;yes, get pixel size
; MOVE.L ((NOPfgColorTable-*).L,PC,D0.W*4),D0
LEA (NOPfgColorTable-*).L,A1 ;get distance from here to NOPfgColorTable
LEA *-6(A1.L),A1 ;get address of "white" table
MOVE.L 0(A1,D0.W*4),D0 ;get default mask for current depth
MOVE.L D0,alphaBack(A6) ;save for later use
MOVE.W D3,D5 ;make copy of adjusted mode
AND.W #$03,D5 ;mask off all but base mode
CMP.W #srcXor,D5 ;are we xoring?
BEQ.S @1 ;yes, use normal default mask
MOVEQ #-1,D0 ;get all ones
@1: MOVE.L D0,alphaMask(A6) ;save default alphaMask
TST portBits+rowBytes(A2) ;is it an old port?
BPL @noalpha ;yes, alpha mode is illegal
MOVE.W dstPix+pixelSize(A6),D0 ;get depth of destination
CMP.W #16,D0 ;direct device?
BLT.S @noalpha ;no, skip this stuff
MOVE.L grafVars(A2),D4 ;get grafvars handle
BEQ @noalpha ;no grafvars, no alpha
MOVE.L D4,A0 ;copy handle
MOVE.L (A0),A1 ;dereference handle
BTST #PmNewGVBit-8,pmFlags(A1) ;make sure grafvars have been expanded
BEQ.S @noalpha ;if not, bail
MOVE.B streamMode(A1),alphaMode(A6);save alpha mode in stack frame
SUB #16,SP ;make room on stack for results
PEA backStream(A1) ;push pointer to background stream and ratio
PEA 12(SP) ;push pointer to where we want results
PEA foreStream(A1) ;push pointer to foreground stream and ratio
PEA 12(SP) ;push pointer to where we want results
_StreamToMask ;get foreground mask for this device
_StreamToMask ;get background mask for this device
MOVE.L (SP)+,D0 ;get alpha mask
MOVE.L (SP)+,D4 ;get alpha fore color
CMP.W #srcXor,D5 ;are we xoring?
BNE.S @2 ;no, use normal default mask
MOVE.L D4,D0 ;yes, use alpha fore color as alpha mask
@2: MOVE.L D0,alphaFore(A6) ;save alpha mask
ADDQ #4,SP ;throw away background mask
MOVE.L (SP)+,D5 ;get alpha back color
MOVEQ #0,D2 ;clear out alpha mask
MOVE.B alphaMode(A6),D0 ;get alpha again
BNE.S @3 ;if non-zero, use that value
MOVEQ #3,D0 ;if zero, draw to both
@3: BTST #1,D0 ;are we drawing to graphics?
BEQ.S @4 ;no, skip
OR.L alphaFore(A6),D2 ;yes, add alpha bits to mask
OR.L D4,D6 ;apply alphaFgColor to the foreground color
OR.L D5,D7 ;apply alphaBkColor to the background color
@4: BTST #0,D0 ;is the alpha going to be drawn?
BEQ.S @5 ;no, then don't apply alpha to fg,bk colors
OR.L alphaBack(A6),D2 ;yes, add graphic bits to mask
@5: MOVE.L D2,alphaMask(A6) ;save alpha mask in stack frame
NOT.L D2 ;check for mask of all ones
SNE alphaMode(A6) ;if mask of all ones, set alphamode to true
@noalpha
MOVE COLRBIT(A2),D2 ;GET COLOR BIT SELECT
MOVEQ #-1,D4 ;DEFAULT VALUE FOR FGLONG
MOVEQ #0,D5 ;DEFAULT VALUE FOR BKLONG
; IF IT IS AN OLD PORT, AND WE ARE GOING TO THE SCREEN, THEN DON'T DO
; SEPARATION, JUST MAP PLANAR COLOR VALUES INTO COLOR INDICES.
; IF IT IS A NEW PORT, DON'T NEED TO REMAP THE VALUES (UNLESS ONE BIT DEEP).
; if pattern mode and new pattern, leave black and white
MOVE D3,D0 ;copy the mode
BCLR #3,D0 ;clear pattern bit
; not necessary since d1 already has pattern bit
; SNE D1 ;remember that the pattern bit was set
CMP #srcXor,D0 ;is it srcXor or patXor?
BEQ COLOROK ;if so, use black/white
CMP #notSrcXor,D0 ;is it notSrcXor or notPatXor?
BEQ COLOROK ;if so, use black/white
TST.B D1 ;IS IT A PATTERN MODE?
BEQ.S DestBitMap ;if not skip, otherwise check if its a multibit pattern <08JUNE92 SAH>
ISPAT
TST.B NEWPATTERN(A6) ;FLAG TRUE IF DESTINATION IS PIXMAP
BEQ.S DestBitMap ;=>YES, GET COLOR PIXEL MASKS
MOVE.L LOCPAT(A6),A0 ;GET PATTERN POINTER
MOVE.L (A0),A0 ;GET HANDLE TO PATTERN
MOVE.L (A0),A0 ;GET POINTER TO PATTERN
TST PATTYPE(A0) ;WHAT TYPE OF PATTERN IS IT?
BNE COLOROK ;=>A NEW ONE, BLACK FG & WHITE BK
DestBitMap
;here src is either an old pattern or image data
TST PORTBITS+ROWBYTES(A2) ;old port or new?
BPL.S REMAP ;if old, go check color bit
jmpROM ciDestBitMap
REMAP TST D2 ;GET COLOR BIT SELECT
BMI COLOROK ;COLRBIT NEG MEANS NO COLOR
BNE.S REMAP2 ;=>DOING PLANES, DO OLD WAY
CMP #1,DSTPIX+PIXELSIZE(A6) ;IS PIXELSIZE 1?
BEQ.S remapOld1bit ;=>yes, REMAP COLORS FOR old 1-bit pixels
jmpROM ciReMapReturn
; From here to COLOROK, the port is old, the destination is 1 bit, the modes are old
remapOld1bit ;Special case colorbit is zero
btst #0,d6
bne.s @fgOK
moveq #0,d4
@fgOK
btst #0,d7
beq.s ColorOK
moveq #-1,d5
ColorOK
jmpROM ciColorOK
; bra.s ColorOK
REP
jmpROM ciRep
REMAP2
jmpROM ciReMap2
ENDPROC
PutPicVerb PROC EXPORT
IMPORT UpdatePat
;------------------------------------------------------
;
; PROCEDURE PutPicVerb(verb: GrafVerb);
;
; Check additional picture params associated with
; this verb, and add those that have changed to thePic.
;
PARAMSIZE EQU 2
VERB EQU PARAMSIZE+8-2 ;BYTE
LINK A6,#0 ;NO LOCAL VARS
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT PORT
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.B VERB(A6),D7 ;GET VERB
CMP.B #PAINT,D7 ;CASE JUMP BASED ON VERB
BLT.S FRAME1
BEQ.S PAINT1 ;YES CHECK PNMODE, PNPAT
CMP.B #INVERT,D7 ;IS VERB INVERT ?
BEQ DONE ;YES, NOTHING TO CHECK
BLT.S ERASE1
FILL1 PEA FILLPAT(A3) ;OLD SRC PTR
MOVE.L FILLPIXPAT(A3),-(SP) ;NEW SRC HANDLE
PEA PICFILLPAT(A4) ;OLD SAVE PTR
MOVE.L PICFILLPP(A4),-(SP) ;NEW SAVE HANDLE
MOVE #opFillPat,-(SP) ;OLD PAT OPCODE
MOVE #opFillPixPat,-(SP) ;NEW PAT OPCODE
JSR UpdatePat ;PUT PAT TO PICT IF NECESSARY
BRA DONE ;=>AND RETURN
;
; This table is repeated 3 places in this file. Sortof sucks.
;
arithMode ;avg addPin addOver subPin trans max subOver min
DC.B srcCopy, srcBic, srcXor, srcOr, srcOr, srcBic, srcXor, srcOr
ERASE1 PEA BKPAT(A3) ;OLD SRC PTR
MOVE.L BKPIXPAT(A3),-(SP) ;NEW SRC HANDLE
PEA PICBKPAT(A4) ;OLD SAVE PTR
MOVE.L PICBKPP(A4),-(SP) ;NEW SAVE HANDLE
MOVE #opBkPat,-(SP) ;OLD PAT OPCODE
MOVE #opBkPixPat,-(SP) ;NEW PAT OPCODE
JSR UpdatePat ;PUT PAT TO PICT IF NECESSARY
BRA DONE ;AND QUIT
FRAME1 MOVE.L PNSIZE(A3),D7 ;GET PNSIZE
CMP.L PICPNSIZE(A4),D7 ;HAS IT CHANGED ?
BEQ.S PAINT1 ;NO, CONTINUE
MOVEQ #opPnSize,D0 ;Get PnSize opcode
jsrROM DPutPicOp ;YES, PUT PNSIZE OPCODE
MOVE.L D7,-(SP)
jsrROM PutPicLong ;PUT NEW PNSIZE
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L D7,PICPNSIZE(A4) ;AND UPDATE STATE VARIABLE
PAINT1 MOVE PNMODE(A3),D7 ;GET PNMODE
CMP PICPNMODE(A4),D7 ;HAS IT CHANGED ?
BEQ.S MODEOK ;NO, CONTINUE
CMP #PICTVERSION,PicVersion(A4) ;IS IT A NEW PICTURE?
BNE.S @DOMODE ;=>YES, NEW MODES OK
BTST #5,D7 ;AN ARITHMETIC MODE?
BEQ.S @DOMODE ;=>NO, MODE IS FINE
AND #$07,D7 ;ELSE STRIP MODE TO BOTTOM 3 BITS
MOVE.B ARITHMODE(D7),D7 ;AND REMAP IT
CMP PICTXMODE(A4),D7 ;HAS IT CHANGED ?
BEQ.S MODEOK ;NO, CONTINUE
@DOMODE MOVEQ #opPnMode,D0 ;GET PNMODE OPCODE
jsrROM DPutPicOp ;YES, PUT PNMODE OPCODE
MOVE D7,-(SP)
jsrROM PutPicWord ;PUT NEW PNMODE
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE D7,PICPNMODE(A4) ;AND UPDATE STATE VARIABLE
MODEOK PEA PNPAT(A3) ;OLD SRC PTR
MOVE.L PNPIXPAT(A3),-(SP) ;NEW SRC HANDLE
PEA PICPNPAT(A4) ;OLD SAVE PTR
MOVE.L PICPNPP(A4),-(SP) ;NEW SAVE HANDLE
MOVE #opPnPat,-(SP) ;OLD PAT OPCODE
MOVE #opPnPixPat,-(SP) ;NEW PAT OPCODE
JSR UpdatePat ;PUT PAT TO PICT IF NECESSARY
DONE MOVEM.L (SP)+,D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'PUTPICVERB'
ENDPROC
StdLine PROC EXPORT
IMPORT PutPicVerb
ciStdLineEntry EQU $29598
ciLineNotPic EQU $2960E
;---------------------------------------------------------------
;
; PROCEDURE StdLine(newPt: Point);
;
PARAMSIZE EQU 4
NEWPT EQU PARAMSIZE+8-4
VARSIZE EQU 0 ;TOTAL SIZE OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D5-D7/A3-A4,-(SP) ;SAVE REGS
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B #FRAME,-(SP) ;PUSH VERB
bsr PutPicVerb ;CHECK pnSize, pnMode, pnPat
jmpROM ciStdLineEntry
NotPic
jmpROM ciLineNotPic
ENDPROC
StdRect PROC EXPORT
IMPORT PutPicVerb
ciStdRectEntry EQU $2C16A
ciRectNotPic EQU $2C178
;---------------------------------------------------------------
;
; PROCEDURE StdRect(verb: GrafVerb; r: Rect);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 6
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
RECT EQU VERB-4 ;LONG, ADDR OF RECT
VARSIZE EQU 0 ;TOTAL SIZE OF LOCALS
LINK A6,#VARSIZE ;NO LOCALS
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP) ;PUSH VERB
bsr PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
jmpROM ciStdRectEntry
NotPic
jmpROM ciRectNotPic
ENDPROC
StdRRect PROC EXPORT
IMPORT PutPicVerb
ciStdRRectEntry EQU $3458A
ciRRectNotPic EQU $345B8
;---------------------------------------------------------------
;
; PROCEDURE StdRRect(verb: GrafVerb; r: Rect; ovWd,ovHt: INTEGER);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 10
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
RECT EQU VERB-4 ;LONG, ADDR OF RECT
OVWD EQU RECT-2 ;WORD
OVHT EQU OVWD-2 ;WORD
LINK A6,#0 ;NO LOCALS
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP) ;PUSH VERB
bsr PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
jmpROM ciStdRRectEntry
NOTPIC
jmpROM ciRRectNotPic
ENDPROC
StdOval PROC EXPORT
IMPORT PutPicVerb
ciOvalEntry EQU $3BA3C
ciOvalNotPic EQU $3BA4C
;---------------------------------------------------------------
;
; PROCEDURE StdOval(verb: GrafVerb; r: Rect);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 6
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
RECT EQU VERB-4 ;LONG, ADDR OF RECT
OVWD EQU -2 ;WORD
OVHT EQU OVWD-2 ;WORD
VARSIZE EQU OVHT ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP)
bsr PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
jmpROM ciOvalEntry
NOTPIC
jmpROM ciOvalNotPic
ENDPROC
StdArc PROC EXPORT
IMPORT PutPicVerb
ciArcEntry EQU $3BB4C
ciArcNotPic EQU $3BB70
;---------------------------------------------------------------
;
; PROCEDURE StdArc(verb: GrafVerb; r: Rect; startAngle,arcAngle: INTEGER);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 10
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
RECT EQU VERB-4 ;LONG, ADDR OF RECT
STARTANG EQU RECT-2 ;WORD
ARCANG EQU STARTANG-2 ;WORD
OVWD EQU -2 ;WORD
OVHT EQU OVWD-2 ;WORD
VARSIZE EQU OVHT ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D4/D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP)
bsr PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
jmpROM ciArcEntry
NOTPIC
jmpROM ciArcNotPic
ENDPROC
StdPoly PROC EXPORT
IMPORT PutPicVerb, DrawPoly
;ciPolyEntry EQU $33B4C
;ciPolyNotPic EQU $33B5C
ciDPutPicOp EQU $32C90
ciPutPicRgn EQU $32CD0
ciGetRect EQU $33B74
ciToFramePoly EQU $33BAA
;---------------------------------------------------------------
;
; PROCEDURE StdPoly(verb: GrafVerb; poly: PolyHandle);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE EQU 6
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
POLY EQU VERB-4 ;LONG, PolyHandle
MINRECT EQU -8 ;RECT
VARSIZE EQU MINRECT ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D5-D7/A2-A4,-(SP) ;SAVE REGS
MOVEQ #0,D7 ;CLEAR LO WORD OF REG SO OPCODE WILL BE OK TO 16BITS <C952/08Nov87> DAF
MOVE.B VERB(A6),D7 ;GET VERB
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP)
bsr PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
; jmpROM ciPolyEntry
;NOTPIC
; jmpROM ciPolyNotPic
MOVEQ #$70,D0 ;PUT POLYNOUN IN HI NIBBLE
ADD D7,D0 ;PUT VERB IN LO NIBBLE
jsrROM ciDPutPicOp ;PUT OPCODE TO THEPIC <26May87 EHB>
MOVE.L POLY(A6),-(SP) ;PUSH POLYHANDLE
jsrROM ciPutPicRgn ;TREAT SAME AS A REGION
; CALL STANDARD LOOP TO DRAW TO ALL DEVICES
NOTPIC PEA StdDraw ;PUSH ADDRESS OF DRAW ROUTINE
peaROM ciGetRect ;PUSH ADDRESS OF RECT ROUTINE
_StdDevLoop ;DRAW TO ALL DEVICES
GOHOME MOVEM.L (SP)+,D5-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDPOLY '
;---------------------------------------------------------------
;
; PROCEDURE StdDraw;
;
; DRAW THE OBJECT
;
StdDraw MOVE.L POLY(A6),A2 ;GET POLYHANDLE
TST.B D7 ;IS VERB FRAME ?
; BNE.S NOTFR ;NO, CONTINUE
; MOVE.L A2,-(SP) ;PUSH POLYHANDLE
; JSR FrPoly ;FrPoly(poly);
; BRA.S DONE ;AND QUIT
BEQ.S ToFrame
NOTFR MOVE.L (A2),A0 ;DE-REFERANCE POLYHANDLE
PEA POLYBBOX(A0) ;PUSH POLYBBOX
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
MOVE #3,-(SP) ;PUSH NRECTS = 3
PEA MINRECT(A6) ;PUT RESULT IN MINRECT
_RSECT ;CALC INTERSECTION
BEQ.S DONE ;QUIT IF NO INTERSECT
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
_PushVerb ;PUSH MODE AND PATTERN
JSR DrawPoly ;DrawPoly(poly,mode,pat);
DONE RTS
ToFrame jmpROM ciToFramePoly
;---------------------------------------------------
;
; PROCEDURE DrawPoly(poly: PolyHandle; mode: integer; VAR pat: Pattern);
;
DrawPoly PROC EXPORT
ciIsRect EQU $3445C
ciNotRect EQU $3447A
ParamSize Equ 10
Poly Equ ParamSize+8-4
Mode Equ Poly-2
Pat Equ Mode-4
PolyRect Equ -8
VarSize Equ PolyRect
; <11Jul88> PMAB543 BAL/JDB Implemented fast case for rectangular filled polys.
Link A6,#VarSize ; local variables
move.l ([poly,a6]),a0 ; pick up polyptr <Begin PMAB543 BAL/JDB>
move (a0)+,d0 ; pick up byte count
cmp #4*5+10,d0 ; quadrilateral?
bne.s @chk4pt ; no, take general case
move.l 8+4*4(a0),d1 ; pick up last pnt
cmp.l 8(a0),d1 ; cmpare with first pnt
bne.s @notRect ;
bra.s @4Pnts
@chk4pt cmp #4*4+10,d0 ; quadrilateral?
bne.s @notRect ; no, take general case
@4Pnts moveq #2,d0 ; force to 4 points
addq #8,a0 ; bump past rect
lea 4(a0),a1 ; point to next point
@nxtPnt SWAP D0 ; swap equality flags into low word <6>
cmp (a0)+,(a1)+ ; cmp h's
seq d1 ; remember equality
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
SUB.B D1,D0 ; if same, set low bit, if not, clear it <6>
cmp (a0)+,(a1)+ ; cmp v's
seq d2 ; remember equality
or.b d2,d1 ; compute h1=h2 | v1=v2
beq.s @notRect ; no, not rect
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
SUB.B D2,D0 ; if same, set low bit, if not, clear it <6>
SWAP D0 ; put counter back in low word <6>
dbra d0,@nxtPnt
SWAP D0 ; swap equality flags into low word <6>
lea -12(a0),a1 ; point to first point
cmp (a0)+,(a1)+ ; cmp h's
seq d1 ; remember equality
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
SUB.B D1,D0 ;if same, set low bit, if not, clear it <6>
cmp (a0)+,(a1)+ ; cmp v's
seq d2 ; remember equality
or.b d2,d1 ; compute h1=h2 | v1=v2
beq.s @notRect ; no, not rect
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
SUB.B D2,D0 ; if same, set low bit, if not, clear it <6>
CMP.B #$99,D0 ; do the equality flags match that of type 1 rectangle ?<6>
BEQ.S @isRect ; yes, use fast case <6>
CMP.B #$66,D0 ; do they match that of a type 2 rectangle ? <6>
BNE.S @notRect ; no, use slow case <6>
@isRect jmpROM ciIsRect
@notRect jmpROM ciNotRect
ENDPROC
StdRgn PROC EXPORT
IMPORT PutPicVerb
ciRgnEntry EQU $35E8C
ciRgnNotPic EQU $35E9E
;---------------------------------------------------------------
;
; PROCEDURE StdRgn(verb: GrafVerb; rgn: RgnHandle);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 6
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
RGN EQU VERB-4 ;LONG, RGNHANDLE
LINK A6,#0 ;NO LOCALS
MOVEM.L D6-D7/A2-A4,-(SP) ;SAVE REGS
MOVEQ #0,D7 ;CLEAR LOWORD OF PICT OPCODE <C952/08Nov87> DAF
MOVE.B VERB(A6),D7 ;GET VERB
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP) ;PUSH VERB
JSR PutPicVerb ;PUT ADDITONAL PARAMS TO THEPIC
jmpROM ciRgnEntry
NOTPIC
jmpROM ciRgnNotPic
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to BitsDevLoop to support changing BaseAddresses
; In addition, if screen devices overlap (only the top-left coordinate is checked,
; don't copy between them.
;
;=========================================================================================
;=========================================================================================
BitsDevLoop PROC EXPORT
ciBitsDevTop EQU $3520C
ciROMCMPTBL EQU $35658
;---------------------------------------------------------------
;
; PROCEDURE DevLoop;
;
; On Entry: A3: GrafPort
; A6: StdBits' stack frame
; DSTBITS(A6): Destination bitmap/pixmap
; RGNA(A6): First region to clip to
; RGNB(A6): Second region to clip to
; MASKBITS(A6): Mask's bitmap
; MASKRECT(A6): Mask's rectangle
;
; D3-D7/A2-A4 have been preserved and can be used.
; SRC DEVICE RECORDS STORED ON STACK
FLAG EQU 0 ;OFFSET TO FLAG
DEV EQU FLAG+2 ;OFFSET TO DEVICE
RECT EQU DEV+4 ;OFFSET TO RECT
SIZE EQU RECT+8 ;SIZE OF RECORD
; Uses StdBits stack frame:
;
PARAMSIZE EQU 18
SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
SRCRECT EQU SRCBITS-4 ;LONG, ADDR OF RECT
DSTRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE EQU DSTRECT-2 ;WORD
MASKRGN EQU MODE-4 ;LONG, RGNHANDLE
SRCPIX EQU -(PMREC+CTREC+20) ;PIXMAP + COLOR TABLE
TEMPPIX EQU SRCPIX-PMREC ;PIXMAP
DSTBITS EQU TEMPPIX-4 ;DST BITMAP
GLOBALSRC EQU DSTBITS-8 ;GLOBAL COPY OF SRC RECT
GLOBALDST EQU GLOBALSRC-8 ;GLOBAL COPY OF DST RECT
SRCRECT1 EQU GLOBALDST-8 ;LOCAL COPY OF SRC RECT
DSTRECT1 EQU SRCRECT1-8 ;LOCAL COPY OF DST RECT (MUST FOLLOW SRCRECT1)
RECT1 EQU DSTRECT1-8 ;RESULT OF INTERSECTION
DEFSRC EQU RECT1-SIZE ;DEFAULT SRC RECORD
ENDSRC EQU DEFSRC-4 ;0 FOR TERMINATING SRC LIST
SRCDEV EQU ENDSRC-4 ;CURRENT SRC DEVICE RECORD
ENDDST EQU SRCDEV-4 ;0 FOR TERMINATING DST LIST
DSTDEV EQU ENDDST-4 ;CURRENT DST DEVICE
SRCLIST EQU DSTDEV-4 ;POINTER TO SORTED SRC RECT LIST
DSTLIST EQU SRCLIST-4 ;POINTER TO SORTED DST RECT LIST
SAVEDSP EQU DSTLIST-4 ;SAVED STACK POINTER
LASTSEED EQU SAVEDSP-4 ;LAST COLOR TABLE SEED
SAVEFG EQU LASTSEED-4 ;ORIGINAL FG COLOR
SAVEBK EQU SAVEFG-4 ;ORIGINAL BK COLOR
SAVEHILITE EQU SAVEBK-2 ;SAVED HILITE MODE FLAG
RGNA EQU SAVEHILITE-4 ;FIRST REGION FOR CLIPPING
RGNB EQU RGNA-4 ;SECOND REGION FOR CLIPPING
MASKBITS EQU RGNB-4 ;BITMAP FOR MASK
MASKRECT EQU MASKBITS-4 ;LONG, ADDR OF MASK RECT
isTmpHandle EQU MASKRECT-1 ;BYTE, FLAG SET IF temp memory used <1.5> BAL
OLDPIC EQU isTmpHandle-1 ;BYTE, FLAG SET IF OLD PICTURE <1.5> BAL
VARSIZE EQU OLDPIC ;TOTAL SIZE OF LOCALS
; IF THERE IS ONLY ONE SCREEN DEVICE, THEN DO IT FAST
MOVE.L DEVICELIST,A0 ;GET HEAD OF DEVICE LIST
MOVE.L (A0),A0 ;POINT TO DEVICE
MOVE.L GDNEXTGD(A0),D0 ;CHECK NEXT DEVICE
BNE.S MANYVIDI ;=>GO DO MANY DEVICES
jmpROM ciBitsDevTop
MANYVIDI
; INITIALIZE THE DEFAULT DESTINATION DEVICE LIST
; THE LIST CONSISTS OF ONE DEVICE HANDLE FOLLOWED BY A 0
MOVE.L SP,SAVEDSP(A6) ;SAVE STACK POINTER
LEA DSTDEV(A6),A1 ;POINT TO START OF DEFAULT DST LIST
MOVE.L A1,DSTLIST(A6) ;SAVE POINTER TO DEFAULT DST LIST
MOVE.L THEGDEVICE,A0 ;GET DEFAULT DEVICE <07Jul88 BAL>
MOVE.L A0,(A1)+ ;DSTDEV := DEFAULT SCREEN DEVICE
CLR.L (A1)+ ;CLEAR FLAG AT END OF DST LIST
; INITIALIZE THE DEFAULT SRC DEVICE LIST
; THE LIST CONSISTS OF ONE RECORD POINTER FOLLOWED BY A 0
MOVE.L A1,SRCLIST(A6) ;SAVE POINTER TO DEFAULT SRC RECORD
LEA DEFSRC(A6),A2 ;POINT TO DEFAULT SRC RECORD
MOVE.L A2,(A1)+ ;INSTALL RECORD POINTER INTO LIST
CLR.L (A1)+ ;CLEAR FLAG AT END OF SRC LIST
MOVE.L A0,DEV(A2) ;INITIALIZE DEVICE FIELD OF RECORD
; DETERMINE WHETHER SRC AND DST ARE THE SCREEN AND SET UP DRAWING DIRECTIONS
; MOVE.L MAINDEVICE,A0 ;GET DEFAULT SCREEN DEVICE <10Jul88 BAL>
; MOVE.L (A0),A0 ;POINT TO DEFAULT SCREEN DEVICE
; MOVE.L GDPMAP(A0),A0 ;GET HANDLE TO PIXMAP
; MOVE.L (A0),A0 ;POINT TO PIXMAP
; MOVE.L BASEADDR(A0),D0 ;GET BASE ADDR OF SCREEN IN D0
MOVE.L ScrnBase,D0 ;GET BASE ADDR OF main SCREEN IN D0 <23Dec89 BAL>
MOVE.L DSTBITS(A6),A0 ;GET DESTINATION IN A0
_BITSTOMAP ;GET BIT/PIXMAP IN A0
; MOVE.L A0,DSTBITS(A6) ; <Don't carry derefed port's pixmap across rgbForeColor>
; <28May89 BAL>
MOVE.L A0,A1 ;KEEP DST PIXMAP IN A1
MOVE.L SRCBITS(A6),A0 ;POINT TO SRC BITMAP
_BITSTOMAP ;GET BIT/PIXMAP IN A0
MOVE.L A0,A2 ;SAVE SRC PIXMAP IN A2
CMP.L BASEADDR(A0),D0 ;SRC FROM THE SCREEN?
SEQ D6 ;IF SO, SET SRCSCRN FLAG
CMP.L BASEADDR(A1),D0 ;DST TO THE SCREEN?
SEQ D7 ;IF SO, SET DSTSCRN FLAG
MOVEQ #6,D2 ;ASSUME COPY FROM TOP TO BOTTOM
MOVE.B D6,D5 ;GET SRC FLAG
AND.B D7,D5 ;D5 SET IF SRC AND DST BOTH SCREEN
BEQ.S DIROK ;=>NO, DON'T WORRY ABOUT OVERLAP
; SRC AND DST BOTH ON SCREEN, AND THERE ARE MULTIPLE SCREENS. DETERMINE TRANSFER DIRECTION
MOVEQ #0,D2 ;ELSE ASSUME TRANSFER DOWN AND TO RIGHT
MOVE.L ([SRCRECT,A6]),D0 ;GET TOPLEFT OF SRCRECT
SUB BOUNDS+LEFT(A0),D0 ;CONVERT LEFT TO GLOBAL COORDINATES
MOVE.L ([DSTRECT,A6]),D1 ;GET TOPLEFT OF DSTRECT
SUB BOUNDS+LEFT(A1),D1 ;CONVERT LEFT TO GLOBAL COORDINATES
CMP D1,D0 ;IS SRC <= DST?
BLE.S TORT ;=>IF SO, TRANSFER IS TO RIGHT
ADDQ #2,D2 ;ELSE TRANSFER TO LEFT
TORT SWAP D0 ;GET TOP OF SRCRECT
SWAP D1 ;GET TOP OF DSTRECT
SUB BOUNDS+TOP(A0),D0 ;CONVERT TOP TO GLOBAL COORDINATES
SUB BOUNDS+TOP(A1),D1 ;CONVERT TOP TO GLOBAL COORDINATES
CMP D1,D0 ;IS SRC <= DST?
BLE.S DIROK ;=>IF SO, TRANSFER IS DOWNWARD
ADDQ #4,D2 ;ELSE TRANSFER IS UPWARD
DIROK leaROM ciROMCMPTBL,A4 ;POINT TO TABLE OF OFFSETS
ADD 0(A4,D2),A4 ;A4 = RECT COMPARE ROUTINE
; COPY SRC RECT AND CONVERT COPY TO GLOBAL COORDINATES
TST.B D6 ;IS SRC THE SCREEN?
BEQ CHKDST ;=>NO, CHECK DEST
MOVE.L SRCRECT(A6),A1 ;POINT TO RECT
LEA GLOBALSRC(A6),A0 ;POINT TO LOCAL COPY
MOVE.L (A1)+,TOPLEFT(A0) ;COPY SRCRECT.TOPLEFT
MOVE.L (A1)+,BOTRIGHT(A0) ;COPY SRCRECT.BOTRIGHT
MOVE.L BOUNDS(A2),D0 ;GET SRCBITS.TOPLEFT
MOVE.L D0,D1 ;LEAVE LEFT IN D0
SWAP D1 ;AND TOP IN D1
SUB D1,(A0)+ ;OFFSET TOP
BVC.S @0 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@0 SUB D0,(A0)+ ;OFFSET LEFT
BVC.S @1 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@1 SUB D1,(A0)+ ;OFFSET BOTTOM
BVC.S @2 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@2 SUB D0,(A0)+ ;OFFSET RIGHT
BVC.S @3 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@3
; FOR EACH SRC DEVICE THAT INTERSECTS WITH THE SRCRECT, BUILD A RECORD ON THE STACK
; EACH RECORD IN LIST CONSISTS OF: [FLAG WORD] [DEVICE HANDLE] [RECTANGLE]
; [FLAG WORD]: O = END OF LIST; 1 = VALID RECORD; -1 = RECORD ALREADY USED IN SORT
MOVE.L DEVICELIST,A2 ;GET HANDLE TO FIRST DEVICE
CLR -(SP) ;[FLAG WORD] := END OF LIST
DONEXT1 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
TST GDFLAGS(A0) ;IS THIS SCREEN ACTIVE?
BPL.S NXTDEV1 ;=>NO, SKIP TO NEXT
CLR.B -(SP) ;MAKE ROOM FOR BOOLEAN RESULT
PEA GLOBALSRC(A6) ;POINT TO SRC RECT
PEA GDRECT(A0) ;POINT AT DEVICE RECT
PEA RECT1(A6) ;GET RESULT IN RECT1
_SECTRECT ;INTERSECT THEM
TST.B (SP)+ ;DID THEY INTERSECT?
BEQ.S NXTDEV1 ;=>NO, KEEP LOOKING
LEA RECT1(A6),A0 ;POINT AT RESULT
MOVE.L 4(A0),-(SP) ;PUSH BOTRIGHT
MOVE.L (A0),-(SP) ;PUSH TOPLEFT
MOVE.L A2,-(SP) ;PUSH CURRENT DEVICE
MOVE #1,-(SP) ;FLAG VALID ENTRY
NXTDEV1 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
MOVE.L GDNEXTGD(A0),D0 ;IS THERE ANOTHER DEVICE IN CHAIN?
MOVE.L D0,A2 ;GET IT INTO A0
BNE.S DONEXT1 ;=>YES, DO NEXT DEVICE
; BUILD SORTED LIST OF POINTERS TO THE DEVICE RECORDS
MOVE.L SP,A2 ;POINT TO FIRST DEVICE
CLR.L -(SP) ;AND FLAG END OF LIST
MOVEQ #0,D1 ;USEFUL CONSTANT
NXTLOOP MOVE.L A2,A0 ;POINT TO START OF LIST
MOVE.L D1,A1 ;INITIALIZE BEST FIT TO NONE
NXTRECT TST FLAG(A0) ;CHECK RECT STATUS?
BMI.S DONEXT ;=>RECT ALREADY USED, SKIP IT
BEQ.S LASTRECT ;=>LAST RECT, DONE WITH THIS LOOP
CMP.L A1,D1 ;SOMETHING TO COMPARE AGAINST?
BEQ.S NORECT ;=>NO, A WINNER BY DEFAULT
JSR (A4) ;COMPARE A0 TO A1
BEQ.S DONEXT ;=>A1 IS BETTER, TRY NEXT
NORECT MOVE.L A0,A1 ;ELSE PUT NEW BEST FIT IN A1
DONEXT ADD #SIZE,A0 ;BUMP TO NEXT RECORD
BRA.S NXTRECT ;=>DO NEXT RECT IN LIST
LASTRECT CMP.L A1,D1 ;DID WE FIND A BEST FIT?
BEQ.S ENDLOOP ;=>NO, ALL DONE
ST FLAG(A1) ;SAY IT'S USED
MOVE.L A1,-(SP) ;AND PUSH RECORD POINTER ONTO STACK
BRA.S NXTLOOP ;=>GO FIND NEXT BEST
ENDLOOP MOVE.L SP,SRCLIST(A6) ;SAVE POINTER TO SRC DEVICE LIST
; COPY DST RECT AND CONVERT COPY TO GLOBAL COORDINATES
CHKDST TST.B D7 ;IS DST THE SCREEN?
BEQ DRAWLOOP ;=>NO, GO TO DRAWING LOOP
MOVE.L DSTRECT(A6),a0 ;POINT TO RECT
LEA GLOBALDST(A6),a1 ;POINT TO LOCAL COPY
MOVE.L (a0)+,TOPLEFT(a1) ;COPY DSTRECT.TOPLEFT
MOVE.L (a0)+,BOTRIGHT(a1) ;COPY DSTRECT.BOTRIGHT
MOVE.L DSTBITS(A6),A0 ;GET DESTINATION IN A0
_BITSTOMAP ;make sure it's not a cportPtr <28May89 BAL>
MOVE.L BOUNDS(a0),D0 ;GET TOPLEFT
MOVE.L D0,D1 ;LEAVE LEFT IN D0
SWAP D1 ;AND TOP IN D1
SUB D1,(a1)+ ;OFFSET TOP
BVC.S @0 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@0 SUB D0,(a1)+ ;OFFSET LEFT
BVC.S @1 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@1 SUB D1,(a1)+ ;OFFSET BOTTOM
BVC.S @2 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@2 SUB D0,(a1)+ ;OFFSET RIGHT
BVC.S @3 ;=>NO OVERFLOW
_PINIT ;ELSE PIN VALUE
@3
; FOR EACH DST DEVICE THAT INTERSECTS WITH THE DSTRECT, BUILD A RECORD ON THE STACK
; EACH RECORD IN LIST CONSISTS OF: [FLAG WORD] [DEVICE HANDLE] [RECTANGLE]
; [FLAG WORD]: O = END OF LIST; 1 = VALID RECORD; -1 = RECORD ALREADY USED IN SORT
MOVE.L DEVICELIST,A2 ;GET HANDLE TO FIRST DEVICE
CLR -(SP) ;[FLAG WORD] := END OF LIST
DONEXT2 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
TST GDFLAGS(A0) ;IS THIS SCREEN ACTIVE?
BPL.S NXTDEV2 ;=>NO, SKIP TO NEXT
CLR.B -(SP) ;MAKE ROOM FOR BOOLEAN RESULT
PEA GLOBALDST(A6) ;POINT TO DST RECT
PEA GDRECT(A0) ;POINT AT DEVICE RECT
PEA RECT1(A6) ;GET RESULT IN RECT1
_SECTRECT ;INTERSECT THEM
TST.B (SP)+ ;DID THEY INTERSECT?
BEQ.S NXTDEV2 ;=>NO, KEEP LOOKING
LEA RECT1(A6),A0 ;POINT AT RESULT
MOVE.L 4(A0),-(SP) ;PUSH BOTRIGHT
MOVE.L (A0),-(SP) ;PUSH TOPLEFT
MOVE.L A2,-(SP) ;PUSH CURRENT DEVICE
MOVE #1,-(SP) ;FLAG VALID ENTRY
NXTDEV2 MOVE.L (A2),A0 ;POINT AT CURRENT DEVICE
MOVE.L GDNEXTGD(A0),D0 ;IS THERE ANOTHER DEVICE IN CHAIN?
MOVE.L D0,A2 ;GET IT INTO A0
BNE.S DONEXT2 ;=>YES, DO NEXT DEVICE
; BUILD SORTED LIST OF DEVICES
MOVE.L SP,A2 ;POINT TO FIRST DEVICE
CLR.L -(SP) ;AND FLAG END OF LIST
MOVEQ #0,D1 ;USEFUL CONSTANT
NXTLUP2 MOVE.L A2,A0 ;POINT TO START OF LIST
MOVE.L D1,A1 ;INITIALIZE BEST FIT TO NONE
NXTRCT2 TST FLAG(A0) ;CHECK RECT STATUS?
BMI.S DONXT2 ;=>RECT ALREADY USED, SKIP IT
BEQ.S LSTRCT2 ;=>LAST RECT, DONE WITH THIS LOOP
CMP.L A1,D1 ;SOMETHING TO COMPARE AGAINST?
BEQ.S NORCT2 ;=>NO, A WINNER BY DEFAULT
JSR (A4) ;COMPARE A0 TO A1
BEQ.S DONXT2 ;=>A1 IS BETTER, TRY NEXT
NORCT2 MOVE.L A0,A1 ;ELSE PUT NEW BEST FIT IN A1
DONXT2 ADD #SIZE,A0 ;BUMP TO NEXT RECORD
BRA.S NXTRCT2 ;=>DO NEXT RECT IN LIST
LSTRCT2 CMP.L A1,D1 ;DID WE FIND A BEST FIT?
BEQ.S ENDLUP2 ;=>NO, ALL DONE
ST FLAG(A1) ;SAY IT'S USED
MOVE.L DEV(A1),-(SP) ;AND PUSH DEVICE HANDLE ONTO STACK
BRA.S NXTLUP2 ;=>GO FIND NEXT BEST
ENDLUP2 MOVE.L SP,DSTLIST(A6) ;SAVE POINTER TO DST DEVICE LIST
DRAWLOOP
; IN CASE WE ARE GOING TO SCREEN, SAVE OFF STATE INFO
MOVE.L THEGDEVICE,-(SP) ;SAVE DST DEVICE
MOVE.L SRCDEVICE,-(SP) ;SAVE SRC DEVICE
MOVE.L THEGDEVICE,A0 ;GET HANDLE TO THE GDEVICE
MOVE.L (A0),A0 ;POINT TO THE GDEVICE
MOVE.L GDPMAP(A0),A0 ;GET HANDLE TO ITS PIXMAP
MOVE.L (A0),A0 ;POINT AT PIXMAP
MOVE.L PMTABLE(A0),A0 ;GET COLOR TABLE HANDLE
MOVE.L (A0),A0 ;POINT TO COLOR TABLE
MOVE.L CTSEED(A0),LASTSEED(A6) ;SAVE LAST COLOR TABLE SEED
MOVE.L FGCOLOR(A3),SAVEFG(A6) ;SAVE FG COLOR
MOVE.L BKCOLOR(A3),SAVEBK(A6) ;SAVE BK COLOR
MOVE.B HiliteMode,saveHilite(A6) ;save the hilite state
; MAKE A LOCAL COPY OF THE SRC AND DST RECTS IN SRCRECT1 AND DSTRECT1
; AND SET D7 TO NON-ZERO IF WE ARE STRETCHING
LEA DSTRECT1(A6),A1 ;POINT TO DSTRECT1, SRCRECT1
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE.L (A0)+,D0 ;GET TOPLEFT
MOVE.L D0,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,D7 ;GET BOTRIGHT
MOVE.L D7,(A1)+ ;COPY BOTRIGHT
SUB D0,D7 ;GET DST WIDTH
SWAP D0 ;GET TOP
SWAP D7 ;GET BOTTOM
SUB D0,D7 ;GET DST HEIGHT
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE.L (A0)+,D0 ;GET TOPLEFT
MOVE.L D0,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,D1 ;GET BOTRIGHT
MOVE.L D1,(A1)+ ;COPY BOTRIGHT
SWAP D7 ;GET DST WIDTH
ADD D0,D7 ;SUBTRACT WIDTH OF SRC
SUB D1,D7 ;FROM WIDTH OF DST
SWAP D7 ;GET HEIGHT
SWAP D0 ;GET TOP
SWAP D1 ;GET BOTTOM
ADD D0,D7 ;SUBTRACT HEIGHT OF SRC
SUB D1,D7 ;FROM HEIGHT OF DST
;D7.L <> 0 IF STRETCHING
; FOR EACH DEVICE IN THE SRCLIST, DRAW TO EACH DEVICE IN THE DSTLIST
MOVE.L SRCLIST(A6),A2 ;POINT TO SRCLIST
NXTSRC MOVE.L DSTLIST(A6),A4 ;POINT TO DSTLIST
MOVE.L (A2)+,D0 ;GET NEXT SRC RECORD
MOVE.L D0,A0 ;GET RECORD POINTER
BEQ DONE ;=>NO MORE
MOVE.L DEV(A0),SRCDEVICE ;AND SET SRC DEVICE
NXTDST MOVE.L (A4)+,D1 ;GET NEXT DST DEVICE
BEQ.S NXTSRC ;=>NO MORE
MOVE.L D1,THEGDEVICE ;ELSE SET DST DEVICE
TST.B D6 ;IS SRC THE SCREEN?
BEQ CLIPOK ;=>NO, DON'T CHECK CLIPPING
;
; if source and destination are both screen devices and they overlap, copy only to
; destination devices which are the same gDevice as the source. This will be needed
; for devices which use a mask plane. It assures that items moved around in the mask
; plane are only copied to the mask plane, and items moved around on the screen are
; only copied to the screen. Without this, the mask would goto the screen and vice-versa.
; <KON 2/19/90>
;
tst.b d5 ;are both src and destination the screen? <KON 23JAN91>
beq.s @cont ;=>NO, Don't check for overlap <104>
cmp.l SRCDEVICE,d1 ;are src and destination the same device? <KON 28NOV90>
beq.s @cont ;=>YES, Don't check for overlap
;
; Src and Dst are different screen devices. If the top-left corner of their rectangles
; are the same, assume the devices overlap and don't copy between them.
;
MOVE.L srcDevice,A1 ;handle to source gDevice
move.l (a1),a1 ;pointer to source gDevice
move.l gdRect(a1),d0 ;get rect top.left
move.l theGDevice,a1 ;handle to destination gDevice
move.l (a1),a1 ;pointer to destination gDevice
cmp.l gdRect(a1),d0 ;dest and src gDevice have same top-left?
beq.s nxtdst ;devices overlap, skip drawing
@cont
;
; End of <KON 2/19/90>
;
; CLIP SRCRECT TO SRC DEVICE BOUNDARIES
MOVE.L -4(A2),A0 ;POINT TO SOURCE RECORD
ADDQ #RECT,A0 ;POINT TO CLIPPED RECT
MOVE.L (A0)+,D0 ;GET GLOBAL CLIPPED.TOPLEFT
MOVE.L (A0)+,D1 ;GET GLOBAL CLIPPED.BOTRIGHT
CMP.L GLOBALSRC+TOPLEFT(A6),D0 ;WAS TOPLEFT TRIMMED?
BNE.S DOTRIM ;=>YES, TRIM SRC, DST RECTS
CMP.L GLOBALSRC+BOTRIGHT(A6),D1 ;WAS BOTRIGHT TRIMMED?
BEQ.S CLIPOK ;=>NO, DON'T TRIM SRC, DST RECTS
DOTRIM MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
LEA DSTRECT1(A6),A1 ;POINT TO DSTRECT1, SRCRECT1
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
SUB GLOBALSRC+LEFT(A6),D0 ;IS LEFT CLIPPED ON DEVICE?
BLE.S @1 ;=>LEFT OK
ADD D0,SRCRECT1+LEFT(A6) ;ELSE TRIM SRC
ADD D0,DSTRECT1+LEFT(A6) ;AND DST
@1 SWAP D0 ;GET TOP
SUB GLOBALSRC+TOP(A6),D0 ;IS TOP CLIPPED ON DEVICE?
BLE.S @2 ;=>TOP OK
ADD D0,SRCRECT1+TOP(A6) ;ELSE TRIM SRC
ADD D0,DSTRECT1+TOP(A6) ;AND DST
@2 SUB GLOBALSRC+RIGHT(A6),D1 ;IS RIGHT CLIPPED ON DEVICE?
BPL.S @3 ;=>RIGHT OK
ADD D1,SRCRECT1+RIGHT(A6) ;ELSE TRIM SRC
ADD D1,DSTRECT1+RIGHT(A6) ;AND DST
@3 SWAP D1 ;GET BOTTOM
SUB GLOBALSRC+BOTTOM(A6),D1 ;IS BOTTOM CLIPPED ON DEVICE?
BPL.S @4 ;=>BOTTOM OK
ADD D1,SRCRECT1+BOTTOM(A6) ;ELSE TRIM SRC
ADD D1,DSTRECT1+BOTTOM(A6) ;AND DST
@4 TST.L D7 ;ARE WE SCALING?
BEQ.S CLIPOK ;=>YES, DON'T NEED TO MAP DST
LEA SRCRECT1(A6),A0 ;ELSE GET TRIMMED SRC
LEA DSTRECT1(A6),A1 ;AND SAVE AS UNMAPPED TRIMMED DST
MOVE.L (A0)+,(A1)+ ;COPY SRCRECT1 TO DSTRECT1
MOVE.L (A0)+,(A1)+
PEA DSTRECT1(A6) ;PUSH RECT TO BE MAPPED
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRC RECTANGLE
MOVE.L DSTRECT(A6),-(SP) ;PUSH DST RECTANGLE
_MAPRECT ;MAP RECTANGLE TO DST COORDINATES
CLIPOK MOVE.B saveHilite(A6),HiliteMode ;RESTORE HILITE FLAGS
TST PORTBITS+ROWBYTES(A3) ;IS IT AN OLD GRAFPORT?
BPL DOIT ;=>YES, COLORS ARE OK
MOVE.L THEGDEVICE,A0 ;GET THE DST DEVICE
MOVE.L (A0),A0 ;POINT AT IT
MOVE.L GDPMAP(A0),A0 ;GET PIXMAP
MOVE.L (A0),A0 ;POINT AT IT
MOVE.L PMTABLE(A0),A0 ;GET COLOR TABLE
MOVE.L (A0),A0 ;POINT AT IT
MOVE.L CTSEED(A0),D0 ;GET SEED
CMP.L LASTSEED(A6),D0 ;SAME AS CURRENT SEED?
BEQ.S DOIT ;=>YES, COLORS ARE OK
MOVE.L D0,LASTSEED(A6) ;SAVE LAST COLOR TABLE SEED
SUBQ #6,SP ;MAKE ROOM FOR A COLOR RECORD
CLR.L -(SP) ;CLEAR INDEX, FLAGS WORDS
; This is a patch rolled in <6Jun87 EHB>
; The idea here is that to keep the index field in the grafPort valid, we must
; check to see whether we should use palette manager or not.
MOVE.L GrafVars(A3),D0 ;get the grafVars handle
BEQ.S @NoPlt ;=>none there
MOVE.L D0,A0 ;get grafVars handle
MOVE.L (A0),A0 ;point at grafVars
TST.L PmFgColor(A0) ;is there a palette?
BEQ.S @NoPlt ;=>no, continue
MOVE PmFlags(A0),D2 ;else get flags
MOVE PmBkIndex(A0),2(SP) ;save bk index
BTST #PmBkBit,D2 ;bk set by palette mgr?
SNE (SP) ;if so set flag
BTST #PmFgBit,D2 ;fg set by palette mgr?
BEQ.S @NoPlt ;=>no, continue
MOVE PmFgIndex(A0),-(SP) ;else push last index
_PmForeColor ;and set that color
BRA.S @NoPlt1 ;=>no, do old way
@NoPlt PEA 4(SP) ;POINT AT RECORD FOR RGBFC
MOVE.L (SP),-(SP) ;AND AGAIN FOR GETFC
_GETFORECOLOR ;GET THE FOREGROUND COLOR
_RGBFORECOLOR ;SET THE FOREGROUND COLOR
@NoPlt1 TST.B (SP) ;bk set by palette mgr?
BEQ.S @NoPlt2 ;=>no, do old way
MOVE 2(SP),-(SP) ;else push bk index
_PmBackColor ;and set that color
BRA.S @BkDone ;=>done setting colors
@NoPlt2 PEA 4(SP) ;POINT AT RECORD
MOVE.L (SP),-(SP) ;AND AGAIN FOR GETFC
_GETBACKCOLOR ;GET THE BACKGROUND COLOR
_RGBBACKCOLOR ;SET THE BACKGROUND COLOR
@BkDone ADD #10,SP ;STRIP THE RECORD
DOIT MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS
MOVE.L MASKBITS(A6),-(SP) ;PUSH MASKBITS
MOVE.L DSTBITS(A6),-(SP) ;PUSH DSTBITS
PEA SRCRECT1(A6) ;PUSH SRCRECT
MOVE.L MASKRECT(A6),-(SP) ;PUSH MASKRECT
PEA DSTRECT1(A6) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
AND #$FFF7,(SP) ;clear the pattern bit in case the user set it
CLR.L -(SP) ;NO PATTERN NEEDED
MOVE.L RGNA(A6),-(SP) ;PUSH FIRST REGION
MOVE.L RGNB(A6),-(SP) ;PUSH SECOND REGION
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK ;WAS IT NIL ?
MOVE.L GRAFGLOBALS(A5),A0 ;GET GRAFGLOBALS
MOVE.L WIDEOPEN(A0),(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK CLR -(SP) ;pass multicolor flag false
_STRETCHBITS ;CALL STRETCHBITS
BRA.S NXTDST ;=>TRY NEXT DESTINATION
DONE MOVE.L (SP)+,SRCDEVICE ;RESTORE SRC DEVICE
MOVE.L (SP)+,THEGDEVICE ;RESTORE DST DEVICE
MOVE.L SAVEFG(A6),FGCOLOR(A3) ;RESTORE FG COLOR
MOVE.L SAVEBK(A6),BKCOLOR(A3) ;RESTORE BK COLOR
BSET #HILITEBIT,HILITEMODE ;TURN OFF HILITING
MOVE.L SAVEDSP(A6),SP ;RESTORE THE STACK POINTER
RTS
ENDPROC
;=========================================================================================
;=========================================================================================
;
; New entry in table below.
;
;=========================================================================================
;=========================================================================================
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
move.w d1,d7 ; get requested luminance as a word <BAL 30Jan90>
sub.w d0,d7 ; get luminance error as a word <BAL 30Jan90>
ENDM
;------------------------------------------------------------------
;
; SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
; ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
; USES: D3: SRC PIXEL SIZE
; D4: DST PIXEL SIZE
; A0: SRC BUFFER
; A1: DST BUFFER
; A2: END OF DST BUFFER
; A4: PIXEL TRANSLATE TABLE
;
; CLOBBERS A0-A1/D0-D5
;
MOVEM.L D6/D7,-(SP) ;SAVE WORK REGISTERS
@1 MOVE.L ErrBuf(a6),A4 ;get ptr to ErrBuf
MOVEQ #0,D5 ;INIT OFFSET INTO DST
MOVE.L D5,D0 ;clear high end
MOVE.L D5,D1 ;clear high end
MOVE.L D5,D2 ;clear high end
not.b errDir(a6) ;check and toggle diffusion direction
bne.s @forward
move.l ErrSrcBuf(a6),a0 ;point to end of srcBuf
moveq #32,d5 ;init dst offset in long
@back2
sub.w D4,D5 ;pre-BUMP TO NEXT DST PIXEL
@backward
sub.w #2,a4
MOVE.L -(A0),D3 ;GET NEXT LONG OF SRC
_DitherBitmap32
asr.w #1,d7 ;get half error (signed)
move.w d7,(a4) ;save 1/2 for next scanline and carry 1/2 to right
sub.w D4,D5 ;BUMP TO NEXT DST PIXEL
bge.s @backward ;TIME FOR NEXT DST LONG? =>NO
moveq #32,d5
MOVE.L D6,-(A2) ;ELSE SAVE CURRENT LONG
CMP.L A2,A1 ;DSTPTR >= DSTLIMIT?
BLO.S @back2 ;if lower, continue to next pixel
move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion
bra.s @donescl
@forward
MOVE.L (A0)+,D3 ;GET NEXT LONG OF SRC
_DitherBitmap32
asr.w #1,d7 ;get half error (signed)
move.w d7,(a4)+ ;save 1/2 for next scanline and carry 1/2 to right
ADD D4,D5 ;BUMP TO NEXT DST PIXEL
AND #$1F,D5 ;TIME FOR NEXT DST LONG?
BNE.S @forward ;=>NO
MOVE.L D6,(A1)+ ;ELSE SAVE CURRENT LONG
CMP.L A2,A1 ;DSTPTR >= DSTLIMIT?
BLO.S @forward ;if lower, continue to next pixel
move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion
move.l a0,ErrSrcBuf(a6) ;point to end of srcBuf for right to left diffusion
@DONESCL
MOVEM.L (SP)+,D6/D7 ;RESTORE WORK REGISTERS
RTS
ENDPROC
;=========================================================================================
;=========================================================================================
;
; New entry in table below.
;
;=========================================================================================
;=========================================================================================
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
move.w d1,d7 ; get requested luminance as a word <BAL 30Jan90>
sub.w d0,d7 ; get luminance error as a word <BAL 30Jan90>
ENDM
;------------------------------------------------------------------
;
; SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
; ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
; USES: D3: SRC PIXEL SIZE
; D4: DST PIXEL SIZE
; A0: SRC BUFFER
; A1: DST BUFFER
; A2: END OF DST BUFFER
; A4: PIXEL TRANSLATE TABLE
;
; CLOBBERS A0-A1/D0-D5
;
MOVEM.L D6/D7,-(SP) ;SAVE WORK REGISTERS
moveq #0,d3 ;clear out high word
@1 MOVE.L ErrBuf(a6),A4 ;get ptr to ErrBuf
MOVEQ #0,D5 ;INIT OFFSET INTO DST
MOVE.L D5,D0 ;clear high end
MOVE.L D5,D1 ;clear high end
MOVE.L D5,D2 ;clear high end
not.b errDir(a6) ;check and toggle diffusion direction
bne.s @forward
move.l ErrSrcBuf(a6),a0 ;point to end of srcBuf
moveq #32,d5 ;init dst offset in long
@back2
sub.w D4,D5 ;pre-BUMP TO NEXT DST PIXEL
@backward
sub.w #2,a4
MOVE.w -(A0),D3 ;GET NEXT LONG OF SRC
_DitherBitmap16
asr.w #1,d7 ;get half error (signed)
move.w d7,(a4) ;save 1/2 for next scanline and carry 1/2 to right
sub.w D4,D5 ;BUMP TO NEXT DST PIXEL
bge.s @backward ;TIME FOR NEXT DST LONG? =>NO
moveq #32,d5
MOVE.L D6,-(A2) ;ELSE SAVE CURRENT LONG
CMP.L A2,A1 ;DSTPTR >= DSTLIMIT?
BLO.S @back2 ;if lower, continue to next pixel
move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion
bra.s @donescl
@forward
MOVE.w (A0)+,D3 ;GET NEXT LONG OF SRC
_DitherBitmap16
asr.w #1,d7 ;get half error (signed)
move.w d7,(a4)+ ;save 1/2 for next scanline and carry 1/2 to right
ADD D4,D5 ;BUMP TO NEXT DST PIXEL
AND #$1F,D5 ;TIME FOR NEXT DST LONG?
BNE.S @forward ;=>NO
MOVE.L D6,(A1)+ ;ELSE SAVE CURRENT LONG
CMP.L A2,A1 ;DSTPTR >= DSTLIMIT?
BLO.S @forward ;if lower, continue to next pixel
move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion
move.l a0,ErrSrcBuf(a6) ;point to end of srcBuf for right to left diffusion
@DONESCL
MOVEM.L (SP)+,D6/D7 ;RESTORE WORK REGISTERS
RTS
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Speedup for Search32toIndexed.
;
;=========================================================================================
;=========================================================================================
MyCProc EQU $3D728
MySProc EQU $3D6FC
;----------------------------------------------------
;
; 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 SeedCFill32, CalcCMask32, Search32toInd
&CurFile SETC 'STRETCH'
INCLUDE 'DrawingVars.a'
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
leaROM MySProc,a2 ;point to seedCFill proc
cmp.l a1,a2 ;are they the same?
bne.s @tryC
lea SeedCFill32,a0
bra.s @gotit
@tryC leaROM 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
ENDPROC
Search32toInd PROC EXPORT
;
; 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
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
;=========================================================================================
;=========================================================================================
;
; Speedup for Search16toIndexed.
;
;=========================================================================================
;=========================================================================================
;----------------------------------------------------
;
; 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.
Search16toIndexed PROC EXPORT
IMPORT SeedCFill16, CalcCMask16
&CurFile SETC 'STRETCH'
INCLUDE 'DrawingVars.a'
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
leaROM 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'
; ...included above...
;------------------------------------------------------------------
;
; 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
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),D3 ;get result in D3
BRA.S BuildLong ;and put into output buffer
OurTurn ;go here if no search proc matched
MOVE.L stITabPtr(A6),A0 ;get pointer to the inverse table (past header)
MOVE.W stITabRes(A6),D1 ;get the iTable resolution
move.b red(sp),d5
BFEXTU D5{24:D1},D0 ;5,8,8 ;extract iTabRes bits of red (clearing hi bits)
LSL.L D1,D0 ;3,6,6 ;shift over by iTabRes
move.b green(sp),d5
BFEXTU D5{24:D1},D3 ;5,8,8 ;get the green component
OR.L D3,D0 ;0,2,3 ;put them together
LSL.L D1,D0 ;3,6,6 ;shift again
move.b blue(sp),d5
BFEXTU D5{24:D1},D3 ;5,8,8 ;get the blue component
OR.L D3,D0 ;0,2,3 ;put them together to form iTable index
;21,40,42
MOVE.B (A0,D0.w),D3 ;get the index in D3 <KON 12MAR90>
BuildLong
BFINS D3,D6{D7:D4} ;PUT TO DST LONG <KON 12MAR90>
ADD D4,D7 ;BUMP TO NEXT DST PIXEL
AND #$1F,D7 ;TIME FOR NEXT DST LONG?
BNE.S NXTSLNG ;=>NO
MOVE.L D6,(A3)+ ;ELSE SAVE CURRENT LONG
CMP.L A2,A3 ;DSTPTR >= DSTLIMIT?
BLO.S NXTSLNG ;if lower, continue to next pixel
DONESCL
moveq #1,d0 ;force 32-bit mode <1.5>
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
ADDA.W #10,SP ;release buffers
MOVEM.L (SP)+,A3-A5/D6-D7 ;RESTORE WORK REGISTERS
RTS
ENDPROC
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
;=========================================================================================
;=========================================================================================
;
; More dither32. This stuff is from ScaleBlt.a
;
;=========================================================================================
;=========================================================================================
;-------------------------------------------------------
;
; seek loop for serpentine dithering with run masks
;
;-------------------------------------------------------
NXTMASKDither PROC EXPORT
EXPORT sc32to8Dither
runMaskBit equ 30 ;bit number for run MASK instruction
move MinRect+bottom(a6),d2 ;get bottom vertical position
sub vert(a6),d2 ;compute scans remaining, prime d2
ble Done
move d2,d3 ;save scans remaining
JSR ([SEEKMASK,A6]) ;MAKE MASK BUFFER CURRENT
move d2,d1 ;get scan count in d1
cmp d3,d1 ;scan count > scans remaining?
ble.s @go ;no, call the blit loop
move d3,d1 ;yes, pin to scans remaining
@go
move.l runBuf(a6),d3 ;save original
move.w #-4,RUNBUMP(a6) ;set transfer direction for seekmask
move.l runBuf2(a6),runBuf(a6) ;point at alternate
JSR ([RUNRTN,A6]) ;MAKE BAKWRDS RUN BUFFER CURRENT
move.l d3,runBuf(a6) ;restore original
move.w #4,RUNBUMP(a6) ;set transfer direction for seekmask
JSR ([RUNRTN,A6]) ;MAKE FORWRDS RUN BUFFER CURRENT
move.l scaleBltA3(a6),A3 ;reload A3 for scan loops
MOVE.L ScaleCase(A6),A2 ;GET MODE CASE JUMP
JMP (A2) ;TAKE MODE JUMP
;-------------------------------------------------------
;
; scale, dither and clip 32-bit src to 8-bit dst
;
;-------------------------------------------------------
; a0 = tmpsrc d0 = src RGB pixel
; a1 = tmpmask d1 = pixel cnt/scratch
; a2 = tmpdst d2 = output pixels
; a3 = ITable d3 = run cnt
; a4 = errBuffer d4 = scratch
; a5 = CLUT d5 = red error
; a6 = locals d6 = grn error
; a7^= scancount d7 = blu error (itabres)
;-------------------------------------------------------
sc32to8Dither
;----------------------------------------------------
;
; 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'
;-------------------------------------------------------
;
; scale, dither and clip 32-bit src to 8-bit dst
;
;-------------------------------------------------------
; a0 = tmpsrc d0 = src RGB pixel
; a1 = tmpmask d1 = pixel cnt/scratch
; a2 = tmpdst d2 = output pixels
; a3 = ITable d3 = run cnt
; a4 = errBuffer d4 = scratch
; a5 = CLUT d5 = red error
; a6 = locals d6 = grn error
; a7^= scancount d7 = blu error (itabres)
;-------------------------------------------------------
;One time initializations here
subq #4,sp ;space for scancount
move.l dstAlign(a6),d0 ; -(# of dst bits to skip)
asr.l #1,d0 ; compute - (# of src bytes to back up)
add.l d0,a4 ; back off src ptr to beginning of dst long
move.l a4,srcAddr(a6) ; save for later
MOVE.L stITabPtr(A6),A3 ; get ptr to ITable
MOVE.L stCLUTPtr(A6),A5 ; get ptr to CLUT
moveq #0,d4 ; clear out high word always
lea @first,a0 ;go here from now on
move.l A3,scaleBltA3(a6) ;save for reload after seekMask
move.l a0,ScaleCase(a6) ;remember for later
bra.s NXTMASKDither ;go to it
align 16
@nxtScan
move.l dstRow(a6),d2 ;get dst rowbytes
add.l d2,dstAddr(a6) ;BUMP DST TO NEXT ROW
move.l srcRow(a6),d2 ;get src rowbytes
add.l d2,srcAddr(a6) ;BUMP src TO NEXT ROW
addq.w #1,vert(a6) ;BUMP DOWN A SCAN LINE
subq #1,(sp) ;decrement scan count
move (sp),d1 ;get back scan count
ble.s NXTMASKDither
@first
move.l srcAddr(a6),a0 ;init tmp src ptr
move.l dstAddr(a6),a2 ;init tmp dst ptr
move.l runBuf(a6),a1 ;point to run encoded mask buffer
move d1,(sp) ;save scan count on stack
MOVE.L ErrBuf(a6),A4 ;get ptr to ErrBuf
MOVEQ #0,D5 ;init redAccum
MOVE.L D5,D6 ;init grnAccum
MOVE.L D5,D7 ;init bluAccum
MOVE.W stITabRes(A6),d7 ;get the iTable resolution
swap d7 ;keep in high word
not.b errDir(a6) ;check and toggle diffusion direction
bne.s @inst ;all ok if going left to right
move.l runBuf2(a6),a1 ;get right to left run buffer
@inst move.l (a1)+,d3 ;pick up next instruction long
bmi.s @nxtScan ;if high bit set then done with scan
add.w d3,a2 ;bump destptr by skip amount
add.w d3,d3 ;bump errbuf by 1x
add.w d3,a4 ;bump errbuf by 2x
add.w d3,d3 ;make dst byte skip src byte skip
add.w d3,a0 ;bump src ptr by 4x
add.w d3,a4 ;bump errbuf by 6x
swap d3 ;get mask/blit
lsl.l #32-runMaskBit,d3 ;shift mask flag into high word
lsr.w #32-runMaskBit,d3 ;clear flags from low word
tst.b errDir(a6) ;check diffusion direction
bne.s @forward ;src is OK for forward travel
@backward
bsr.s ditherCore8
sub.w #48,a4 ;bump back by 4+4 error pixels
sub.w #32,a0 ;bump back by 4+4 src pixels
btst #16,d3 ;check mask flag
beq.s @bblit ;no mask
MOVE.L (A1)+,D0 ;GET MASK
AND.L D0,D2 ;MASK src DATA
NOT.L D0 ;MAKE NOTMASK
AND.L (A2),D0 ;GET DST DATA
OR.L D0,D2 ;MERGE WITH PAT DATA
@bblit MOVE.L D2,(A2) ;PUT RESULT TO DST
subq #4,a2 ;bump the dst
DBRA D3,@backward ;LOOP ALL PIXELS THIS RUN
BRA.s @inst ;LOOP BACK FOR more runs
@forward
bsr.s ditherCore8
btst #16,d3 ;check mask flag
beq.s @fblit ;no mask
MOVE.L (A1)+,D0 ;GET MASK
AND.L D0,D2 ;MASK src DATA
NOT.L D0 ;MAKE NOTMASK
AND.L (A2),D0 ;GET DST DATA
OR.L D0,D2 ;MERGE WITH PAT DATA
@fblit MOVE.L D2,(A2)+ ;PUT RESULT TO DST
DBRA D3,@forward ;LOOP ALL PIXELS THIS RUN
BRA.s @inst ;LOOP BACK FOR more runs
DitherCore8
moveq #3,d1 ;4 per dst long; clear high 3 bytes
@nxtSrc
swap d1 ;save pixel cnt in high word
move.l (a0)+,d0 ;fetch next src pixel
move.b d0,d4 ;get blue as a word
add.w 4(a4),D7 ;consume blu error from above
add.w d4,d7 ;accumulate blue
spl d4 ;get pin value if neg
cmp.w d4,d7 ;is it too big
sgt d1 ;get pin value if too big
and d4,d7 ;mask to zero or a byte
or d1,d7 ;conditionally pin to ff
lsr.w #8,d0 ;toss blue
add.w 2(a4),D6 ;consume grn error from above
add.w d0,d6 ;accumulate green
spl d4 ;get pin value if neg
cmp.w d4,d6 ;is it too big
sgt d1 ;get pin value if too big
and d4,d6 ;mask to zero or a byte
or d1,d6 ;conditionally pin to ff
swap d0 ;toss green
move.b d0,d4 ;get red as a word
add.w (a4),D5 ;consume red error from above
add.w d4,d5 ;accumulate red
spl d4 ;get pin value if neg
cmp.w d4,d5 ;is it too big
sgt d1 ;get pin value if too big
and d4,d5 ;mask to zero or a byte
or d1,d5 ;conditionally pin to ff
move.l d7,d0 ;get the iTable resolution in high word
swap d0 ;move it to low word
move.b d5,d4 ;get desired red value
lsl.l d0,d4 ;move it up
move.b d6,d4 ;get desired grn value
lsl.l d0,d4 ;move it up
move.b d7,d4 ;get desired blu value
neg d0
addq #8,d0
lsr.l d0,d4 ;throw out the insignificant bits
move.b (a3,d4.L),d1 ;get the index in D1.w (hi byte still clear)
lsl.l #8,d2 ;shift other pixels up to make room
move.b d1,d2 ;save this pixel
move.l CTTable+rgb+red(a5,d1.w*8),d0 ;get RRRRGGGG
moveq #0,d4 ;clear out high end
lsr.l #8,d0 ;get high byte of green
move.b d0,d4 ;make it a word
sub.w d4,d6 ;compute green error
swap d0 ;get high byte of red
sub.w d0,d5 ;compute red error
move.b CTTable+rgb+blue(a5,d1.w*8),d4 ;get BBBB
sub.w d4,d7 ;compute blue error
MOVEQ #0,D4 ;GET A HANDY KONSTANT
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 D4,D5 ;KEEP NEGATIVE NUMBERS FROM DRIFTING AWAY FROM ZERO
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 D4,D6 ;KEEP NEGATIVE NUMBERS FROM DRIFTING AWAY FROM ZERO
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 D4,D7 ;KEEP NEGATIVE NUMBERS FROM DRIFTING AWAY FROM ZERO
swap d1 ;get back pixel cnt
dbra d1,@nxtSrc ;do for each src pixel in this dst long
rts
Done MoveQ #1,d0 ;return success
MOVE.L SAVESTK2(A6),SP ;RESTORE STACK POINTER
RTS ;AND RETURN TO STRETCHBITS
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Table from ScaleBlt.a moved to RAM.
;
;=========================================================================================
;=========================================================================================
;8-Bit Blits
RAMscDirTab8 PROC EXPORT
scCopy16toIndexed EQU $0
scDither16 EQU $0
scGray16 EQU $0
scDitherGray16 EQU $0
sc32to8 EQU $0
sc32to8gray EQU $0
;sc32to8Dither ;patched out below
DC.L scCopy16toIndexed-RAMscDirTab8 ;0 16 to 8
DC.L scDither16-RAMscDirTab8 ;1 16 to 8 dither
DC.L scGray16-RAMscDirTab8 ;2 16 to 8 gray
DC.L scDitherGray16-RAMscDirTab8 ;3 16 to 8 gray+dither
DC.L sc32to8-RAMscDirTab8 ;4 32 to 8
DC.L sc32to8Dither-RAMscDirTab8 ;5 32 to 8 dither
DC.L sc32to8gray-RAMscDirTab8 ;6 32 to 8 gray
DC.L sc32to8gray-RAMscDirTab8 ;7 32 to 8 gray+dither
;*** should probably do a 32to8gray dither as well ***
ENDPROC
;
;=========================================================================================
;=========================================================================================
;
; Quickerdraw patches.
;
;=========================================================================================
;=========================================================================================
patchciROM EQU 1
INCLUDE 'Arith8Blt.a'
;=========================================================================================
;=========================================================================================
;
; Patch 32toIndexed to eliminate accumulation of dither error.
;
;=========================================================================================
;=========================================================================================
Dither32toIndexed PROC EXPORT
ditherCore32 EQU $39432
;----------------------------------------------------
;
; 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
jsrROM ditherCore32
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
jsrROM ditherCore32
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
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch Dither32toGray to eliminate accumulation of dither error.
;
;=========================================================================================
;=========================================================================================
Dither32toGray PROC EXPORT
;----------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
; STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile SETC 'STRETCH'
INCLUDE 'DrawingVars.a'
MACRO
_DitherGray
move.b d3,d2 ; get the blue component
lsr.l #8,d3 ; get red,green in low word
move.b d3,d1 ; get the green component
lsr.w #8,d3 ; get red in low byte
move.b d3,d0 ; get the red component
; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2
add.w d1,d3
add.w d2,d3
add.w d2,d3
lsr.w #2,d3
add.w d0,d3
add.w d1,d3
add.w d1,d3
lsr.w #2,d3
add.w d3,d7 ; consume error from right (or left)
add.w (a4),d7 ; consume error from above
spl d2 ; get pin value if neg
cmp.w d2,d7 ; is it too big
sgt d1 ; get pin value if too big
and.b d2,d7 ; pin to zero
or.b d1,d7 ; pin to 255
move.b d7,d1 ; extend to a word
move.b (a3,d1),d0 ; pick up index for this luminance
BFINS D0,D6{D5:D4} ; PUT TO DST LONG
move.w d1,d7 ; get requested luminance as a word <BAL 30Jan90>
move.b (a5,d1),d1 ; get actual luminance as a word <BAL 30Jan90>
sub.w d1,d7 ; get luminance error as a word <BAL 30Jan90>
ENDM
;------------------------------------------------------------------
;
; SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED
; ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
;
; USES: D3: SRC PIXEL SIZE
; D4: DST PIXEL SIZE
; A0: SRC BUFFER
; A1: DST BUFFER
; A2: END OF DST BUFFER
; A4: PIXEL TRANSLATE TABLE
;
; CLOBBERS A0-A1/D0-D5
;
MOVEM.L A3/A5/D6/D7,-(SP) ;SAVE WORK REGISTERS
MOVE.L stITabInfo(A6),A3 ;get pointer to the luminance table (past header)
lea ITabLuma-ITabInfo(a3),a5 ;point to luma table
@1 MOVE.L ErrBuf(a6),A4 ;get ptr to ErrBuf
MOVEQ #0,D5 ;INIT OFFSET INTO DST
MOVE.L D5,D0 ;clear high end
MOVE.L D5,D1 ;clear high end
MOVE.L D5,D2 ;clear high end
not.b errDir(a6) ;check and toggle diffusion direction
bne.s @forward
move.l ErrSrcBuf(a6),a0 ;point to end of srcBuf
moveq #32,d5 ;init dst offset in long
@back2
sub.w D4,D5 ;pre-BUMP TO NEXT DST PIXEL
@backward
sub.w #2,a4
MOVE.L -(A0),D3 ;GET NEXT LONG OF SRC
_DitherGray
moveq #0,d3 ; <23Feb90 KON>
asr.w #1,d7 ;get half error (signed)
move.w d7,(a4) ;save 1/2 for next scanline and carry 1/2 to right
addx.w d3,d7 ;prevent error from accumulating <23Feb90 KON>
sub.w D4,D5 ;BUMP TO NEXT DST PIXEL
bge.s @backward ;TIME FOR NEXT DST LONG? =>NO
moveq #32,d5
MOVE.L D6,-(A2) ;ELSE SAVE CURRENT LONG
CMP.L A2,A1 ;DSTPTR >= DSTLIMIT?
BLO.S @back2 ;if lower, continue to next pixel
move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion
bra.s @donescl
@forward
MOVE.L (A0)+,D3 ;GET NEXT LONG OF SRC
_DitherGray
moveq #0,d3 ; <23Feb90 KON>
asr.w #1,d7 ;get half error (signed)
move.w d7,(a4)+ ;save 1/2 for next scanline and carry 1/2 to right
addx.w d3,d7 ;prevent error from accumulating <23Feb90 KON>
ADD D4,D5 ;BUMP TO NEXT DST PIXEL
AND #$1F,D5 ;TIME FOR NEXT DST LONG?
BNE.S @forward ;=>NO
MOVE.L D6,(A1)+ ;ELSE SAVE CURRENT LONG
CMP.L A2,A1 ;DSTPTR >= DSTLIMIT?
BLO.S @forward ;if lower, continue to next pixel
move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion
move.l a0,ErrSrcBuf(a6) ;point to end of srcBuf for right to left diffusion
@DONESCL
MOVEM.L (SP)+,A3/A5/D6/D7 ;RESTORE WORK REGISTERS
RTS
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch Dither16toGray to eliminate accumulation of dither error.
;
;=========================================================================================
;=========================================================================================
Dither16toGray PROC EXPORT
;----------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
; STACKFRAME LINKED AND LOCALS INITIALIZED BY STRETCHBITS.
;
&CurFile SETC 'STRETCH'
INCLUDE 'DrawingVars.a'
MACRO
_DitherGray16
lsl.l #3,d3 ; left justify lo 5 bits
move.b d3,d2 ; get the blue component
lsl.w #5,d2 ; save 5 bits
move.b d3,d2 ; get 5 more bits
lsr.w #5,d2 ; chuck 2 of the ten
lsr.l #5,d3 ; left justify lo 5 bits
move.b d3,d1 ; get 5 of the green bits
lsl.w #5,d1 ; save 5 bits
move.b d3,d1 ; get 5 more bits
lsr.w #5,d1 ; chuck 2 of the ten
lsr.l #5,d3 ; left justify lo 5 bits
move.b d3,d0 ; get 5 of the red bits
lsl.w #5,d0 ; save 5 bits
move.b d3,d0 ; get 5 more bits
lsr.w #5,d0 ; chuck 2 of the ten
move.w d0,d3 ; make a copy of the red
; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2
add.w d1,d3
add.w d2,d3
add.w d2,d3
lsr.w #2,d3
add.w d0,d3
add.w d1,d3
add.w d1,d3
lsr.w #2,d3
add.w d3,d7 ; consume error from right (or left)
add.w (a4),d7 ; consume error from above
spl d2 ; get pin value if neg
cmp.w d2,d7 ; is it too big
sgt d1 ; get pin value if too big
and.b d2,d7 ; pin to zero
or.b d1,d7 ; pin to 255
move.b d7,d1 ; extend to a word
move.b (a3,d1),d0 ; pick up index for this luminance
BFINS D0,D6{D5:D4} ; PUT TO DST LONG
move.w d1,d7 ; get requested luminance as a word <BAL 30Jan90>
move.b (a5,d1),d1 ; get actual luminance as a word <BAL 30Jan90>
sub.w d1,d7 ; get luminance error as a word <BAL 30Jan90>
ENDM
;------------------------------------------------------------------
;
; SCALES A SCANLINE OF PIXELS FROM 16 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
;=========================================================================================
;=========================================================================================
;
; Move stColorTab to RAM to patch direct dither entries.
; This PROC doesn't do anything, it only holds space for the RAM table.
; Code below the CutBack point installs the table.
;
;=========================================================================================
;=========================================================================================
RAMstColorTab PROC EXPORT
IMPORT Dither16toIndexed
ALIGN 4
Bogus EQU 0
Scale32toIndexed EQU 0
Scale32to16 EQU 0
;Dither32toIndexed EQU 0 ;new routine is above
Scale16to32 EQU 0
Scale16toIndexed EQU 0
;Dither16toIndexed EQU 0
;Color Blits EQU 0
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
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Table from Stretch.a moved to RAM.
;
;=========================================================================================
;=========================================================================================
RAMstGrayTab PROC EXPORT
;Gray Blits
Scale32toBitmap EQU $0
Scale32toGray EQU $0
;Dither32toBitmap EQU $0 This routine added above
;Dither32toGray EQU $0 This routine added above
Scale16ToBitMap EQU $0
Scale16toGray EQU $0
;Dither16toBitmap EQU $0 This routine added above
;Dither16toGray EQU $0 This routine added above
stGrayTab
DC.L Scale32toBitmap-stGrayTab ;8 32 to BitMap
DC.L Scale32toGray-stGrayTab ;9 32 to Indexed
DC.L Dither32toBitmap-stGrayTab ;A 32 to (16) ->BitMap Dither <BAL 28Jan90>
DC.L Dither32toGray-stGrayTab ;B 32 to Indexed Dither
DC.L Scale16ToBitMap-stGrayTab ;C 16 to BitMap
DC.L Scale16toGray-stGrayTab ;D 16 to Indexed
DC.L Dither16toBitmap-stGrayTab ;E 16 to (16) ->BitMap Dither <BAL 28Jan90>
DC.L Dither16toGray-stGrayTab ;F 16 to Indexed Dither
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Table from Stretch.a now resides totally in RAM
;
;=========================================================================================
;=========================================================================================
RAMstSearchTab PROC EXPORT
IMPORT Search32to32, Search32toIndexed
IMPORT Search32to16, Search16to32
IMPORT Search16toIndexed, Search16to16
Bogus EQU $0
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
ENDPROC
;=========================================================================================
;=========================================================================================
;
; All the new search procs follow.
;
;=========================================================================================
;=========================================================================================
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
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
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
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
;=========================================================================================
;=========================================================================================
;
; Dither16toIndexed patched to replicate high 3 bits of each channel of 16 bit color
; to the low three bits. This prevents error from accumulating "out of nowhere."
;
;=========================================================================================
;=========================================================================================
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)+,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
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch SetupStretch to add support for 16-bit shrinking.
;
;=========================================================================================
;=========================================================================================
SetupStretch PROC EXPORT
&CurFile SETC 'STRETCH'
INCLUDE 'DrawingVars.a'
;----------------------------------------------------
;
; 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
;--------------------------------------------------------------
;
; 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, horizfraction in D0.
;
; Call resulting case jump with:
;
; A0: srcPtr
; A1: dstPtr
; A2: dstLimit
; D4: horizfraction
;
; clobbers D0-D4,A0-A1
;
ciDONE EQU $37934
ciONE EQU $38570
ciStrching EQU $38460
ciFound EQU $384E4
ciFastRatios EQU $384FE
ciPIXSHRNK EQU $392F8
ci32Shrink EQU $39270
MOVE D3,-(SP) ;SAVE SRC DEPTH
leaROM ciDONE,A0 ;POINT TO ABORT
TST D0 ;IS NUMER <= 0 ?
BLE.s FOUND ;YES, POINT TO ABORT
TST D1 ;IS DENOM <= 0 ?
BLE.s FOUND ;YES, POINT TO ABORT
leaROM ciONE,A0 ;POINT TO FAST COPY
CMP D1,D0 ;IS NUMER = DENOM ?
BEQ.s FOUND ;YES, USE FAST COPY
BLT.s SHRNKING ;NO, BRANCH IF SHRINKING
jmpROM ciStrching
;
; 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
leaROM ciPIXSHRNK,A0 ;ASSUME WE'RE SHRINKING PIXELS
move.w (SP),d3 ;check source depth
beq.s ciCheckFast
cmp.w #4,d3 ;16-bit or greater
blt.s Found ;No, 8 bits or less. Assumption correct
beq.s Do16Shrink
leaROM ci32Shrink,a0
bra.s Found
Do16Shrink
lea averageH16,a0
Found
jmpROM ciFound
ciCheckFast
jmpROM ciFastRatios
averageH16
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
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 @Done ;=>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
@done MOVEM.L (SP)+,D5/A5 ;RESTORE WORK REGISTERS
RTS
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Complete replacement for Stretch, stScanLoop, BlitCase, and 16 and 32-bit arith blit
; loops
;
;=========================================================================================
;=========================================================================================
;
; Output: A3 contains address of current scanline.
;
MACRO
_pmVersion
add.l a5,a3 ;bump src to next row
ENDM
;
; The first time bruce is called, D3 contains the starting scan line number
; On output: A3 contains first scanline address
;
MACRO
_pmVersionSrcFirstTime
ENDM
MACRO
_pmVersionMaskFirstTime
ENDM
StretchBits PROC EXPORT
IMPORT Scale32toIndexed, Scale16toIndexed, ScaleIndexedToIndexed, Scale32ToBitMap
IMPORT Scale32toGray, Scale16toGray, Scale32to16, Scale16ToBitMap
IMPORT Search32toIndexed, Search16toIndexed, Search32to16, Search16to32
IMPORT Dither32toIndexed, Dither16toIndexed, Dither32toGray, Dither16toGray
IMPORT Dither32toBitmap, Dither16toBitmap
IMPORT scaleBlt
EXPORT stScanLoop, BlitCase, stMask0, stArith16Tab, stArith32Tab
EXPORT NOPfgColorTable
ciROMTable2 EQU $38846
ciROMTable4 EQU $38AE8
ciROMTable8 EQU $38FF4
ciScale16to32 EQU $39C80
SHFTTBL EQU $304B6
ciCB8to8Clip EQU $3A8E0
ciCB1to8Clip EQU $3A680
ciCB8to1Clip EQU $3AC6E
;--------------------------------------------------------------
;
; 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
ciFromDrawLine EQU $29B84
ciFromFrameRect EQU $2C608
;----------------------------------------------------
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 <121> <09JUN92 SAH>
;
; Copy rectangles to stack since they might be part of a handle and could move.
; Some people don't know that CopyBits moves memory... just call me SlowDraw.
; <KON 7NOV90>
;
move.l srcrect(a6),a0
lea newSrcRect(a6),a1
move.l a1,srcrect(a6)
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
move.l maskrect(a6),a0
lea newMaskRect(a6),a1
move.l a1,maskrect(a6)
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
move.l dstrect(a6),a0
lea newDstRect(a6),a1
move.l a1,dstrect(a6)
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
MOVE.W MODE(A6),D1 ;get mode
cmpRA ciFromDrawLine,4(A6) ;are we coming from drawline?
BEQ.S @getstream ;yes, then force it through GetStreamMode
cmpRA ciFromFrameRect,4(A6) ;are we coming from framerect?
BEQ.S @getstream ;yes, then force it through GetStreamMode
BTST #3,D1 ;pattern mode?
BNE.S @0 ;yes, skip because alpha mode already stripped
@getstream
_GetStreamMode ;get alpha mode bits
MOVE.W D1,MODE(A6) ;get new stripped mode
@0: MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL POINTER
move.b mmu32Bit,MMUSave(a6) ;save mmu mode for cheap exit
CLR.L DSTMASKBUF(A6) ;ASSUME NO MASK
CLR.L stackHandle(A6) ;init alternate stack not used
;----------------------------------------------------------------
;
; MAKE SURE THE STACK IS ON A LONGWORD BOUNDARY (FOR FAST BUFFERS)
;
MOVE.L SP,D1 ;GET THE STACK POINTER
AND.B #$FC,D1 ;FORCE LONG ALIGNMENT
MOVE.L D1,SP ;USE IT
;----------------------------------------------------
;
; CONVERT SRCBITS AND DSTBITS TO PIXMAPS
; (A5 must contain global ptr)
;
; BITSTOPIX TAKES DEFAULT DEVICE FROM THEGDEVICE
MOVE.L THEGDEVICE,-(SP) ;SAVE THEGDEVICE
MOVE.L SRCDEVICE,THEGDEVICE ;SET UP SRC DEVICE
MOVE.L SRCBITS(A6),A1 ;GET POINTER TO SRCBITS
IF useColorICON THEN
;----------------------------------------------------
; SLIMEY HACK to draw Jackson Pollack Icon in Full Color:
;
move.l baseAddr(a1),d0 ;get baseAddr
_rTranslate24To32 ;clean up the address
clr.w filler2(a6) ;set myIcon flag false
tst.l d0 ;is it in slot space?
bmi.s @1 ;yes, skip chk
move.l d0,a0 ;to prevent Bus Errors
; cmp.l #$EBF557E2,108(a0) ;check for race car signature
; cmp.l #$cc45c929,108(a0) ;check for painting signature
lea 80(a0),a0 ;point into data
cmp.l #$842ba003,(a0)+ ;check for prism signature
bne.s @1
cmp.l #$8445d455,(a0)+ ;check for prism signature
bne.s @1
cmp.l #$8882e803,(a0)+ ;check for prism signature
bne.s @1
cmp.l #$89017855,(a0) ;check for prism signature
bne.s @1
move.l jpCicn,a1 ; get cicn handle
move.l (a1),a1 ; point at pixmap
move.l (sp),a0 ; get the dst gdevice handle
move.l (a0),a0 ; point to it
move.l gdPMap(a0),a0 ; get its pixmap handle
move.l (a0),a0 ; point to it
cmp.w #4,pixelsize(a0) ; check depth
bge.s @usePMap ; 4 bit or deeper-> use pixmap data
add #IconBMap,a1 ; else use bitmap data
sub #1,filler2(a6) ; using bitmap, don't hack colors
@usePMap
cmp.w #3,Mode(a6) ; BIC mode?
bne.s @2 ; no, draw the icon
bra done
@2 clr.w Mode(a6) ; use copy mode
add #1,filler2(a6) ; flag hack in progress
;
;----------------------------------------------------
ENDIF
@1 LEA SRCPIX(A6),A2 ;COPY INTO SRCPIX
_BitsToPix ;BITMAP -> PIXMAP
MOVE.L (SP)+,THEGDEVICE ;RESTORE THEGDEVICE AS DST DEVICE
MOVE.L DSTBITS(A6),A1 ;GET POINTER TO DSTBITS
LEA DSTPIX(A6),A2 ;COPY INTO DSTPIX
_BitsToPix ;BITMAP -> PIXMAP
MOVE.L D1,REALBOUNDS(A6) ;SAVE REAL DST BOUNDS.TOPLEFT
MOVE.B D2,CRSRFLAG(A6) ;REMEMBER IF DST IS SCREEN <BAL 18Sep88>
;----------------------------------------------------
;
; GET SHIFT AMOUNTS FOR SRC (D3) AND DST (D4) DEPTHS
; THE PIXSRC FLAG IS SET IF SRC IS A PIXMAP THAT ISN'T ONE BIT PER PIXEL
;
LeaROM 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
LEAROM 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
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
skipTable
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
;
; fcolor and bcolor were mapped using search proc by colormap. We want to use
; the unmapped versions.
;
PEA RGBFrColor(a6) ;get fg color for colorizing
PEA RGBBgColor(a6)
move.w d0,XLateFlag(a6) ;save translation flags <KON 5MAR91>
_GetBackColor ;get bg color for colorizing
_GetForeColor
move.w XLateFlag(a6),d0 ;restore translation flags <KON 5MAR91>
cmp.w #4,d4 ; 16-Bit?
beq.s @Do16Bit ;
;
; Convert RGB colors to 32-bit colors for foreground
;
moveq #0,d1
move.b RGBFrColor(a6),d1 ;red
swap d1
move.b RGBFrColor+2(a6),d1 ;green
lsl #8,d1
move.b RGBFrColor+4(a6),d1 ;blue
move.l d1,fcolor(a6)
moveq #0,d1 ;do background
move.b RGBBgColor(a6),d1 ;red
swap d1
move.b RGBBgColor+2(a6),d1 ;green
lsl #8,d1
move.b RGBBgColor+4(a6),d1 ;blue
move.l d1,bcolor(a6)
bra.s @CheckSwapping
@Do16Bit
;
; Convert RGB colors to 32-bit colors for background
;
moveq #0,d1
move.b RGBFrColor(a6),d1 ;red
lsl #5,d1 ; rrrrrrrr00000
move.b RGBFrColor+2(a6),d1 ;green rrrrrgggggggg
lsl.l #5,d1 ; rrrrrgggggggg00000 <KON 5MAR91>
move.b RGBFrColor+4(a6),d1 ;blue rrrrrgggggbbbbbbbb
lsr.l #3,d1 ; 000rrrrrgggggbbbbb <KON 5MAR91>
move.w d1,fcolor(a6)
move.w d1,fcolor+2(a6)
moveq #0,d1
move.b RGBBgColor(a6),d1 ;red
lsl #5,d1
move.b RGBBgColor+2(a6),d1 ;green
lsl.l #5,d1 ; <KON 5MAR91>
move.b RGBBgColor+4(a6),d1 ;blue
lsr.l #3,d1 ; <KON 5MAR91>
move.w d1,bcolor(a6)
move.w d1,bcolor+2(a6)
@CheckSwapping
btst.l #SwapFGBGBit,d0 ;swap fg/bg colors?
beq.s swapdone
swapfgbk
move.l fcolor(a6),d1 ;swap fg/bk color
move.l bcolor(a6),fcolor(a6)
move.l d1,bcolor(a6)
swapdone
;------------------------------------------------------------------------------
; Check if colorizing is a NOP. If it is, clear the colorize bits.
; There are three cases: ModeCase, ScaleCase, and SrcBuf colorizing
;
; SrcBuf and ScaleCase colorizing is a NOP IF
;
; for 1-bit sources:
; fcolor = $FFFFFFFF and bcolor = 0
;
; for deep sources:
; RGBFrColor = 0 and RGBBgColor = $00FFFFFF (32-bit)
; or RGBBgColor = $7FFF7FFF (16-bit)
;
; ModeCase colorizing is NOP if bcolor=0 and fcolor=NOPfgColorTable
;
; If ModeCase or ScaleCase colorizing, check for NOP
;
btst.l #ColorizeInModeCaseBit,d0
beq @CheckColorizeInSrcBuf ;branch if SrcBuf or ScaleCase colorizing
;
; Do ModeCase NOP check
;
move.l bcolor(a6),d1 ;is bg color a NOP ($00000000)?
bne @CheckColorizeNOPDone ;bk not a NOP, go slow
move.l fcolor(a6),d1 ;is fg color a NOP?
lea NOPfgColorTable,a0
cmp.l (a0,d4*4),d1
bne @CheckColorizeNOPDone ;no, it's not a NOP
;
; It's a NOP, clear colorize bits
;
and.w #~(ColorizeInModeCase),d0 ;turn off modecase colorizing
bra @CheckColorizeNOPDone
@CheckColorizeInSrcBuf
;
; Check SrcBuf or ScaleCase colorizing
;
; if src is indexed and destination indexed:
; NOP if fcolor = $FFFFFFFF and bcolor = 0
; if src is indexed and destination is direct:
; NOP if fcolor = 0 and bcolor = $00FFFFFF (32-bit)
; bcolor = $7FFF7FFF (16-bit)
;
; Get fg and bg color in RGB space if colorizing at srcbuf, since our source is
; still in RGB space at that time.
;
; D3 contains src pixel depth.
; D4 contains dst pixel depth.
;
cmp.w #4,d3 ;deep src?
bge.s @DeepSrc
cmp.w #4,d4 ;dst indexed?
bge.s @DoDirectNOPCheck
tst.l bcolor(a6) ;bcolor a NOP?
bne @CheckColorizeNOPDone
move.l fcolor(a6),d1 ;fcolor a NOP?
addq.l #1,d1
bne @CheckColorizeNOPDone
bra.s @ClearColorizeBits ;it's a NOP, clear the colorize bits
@DoDirectNOPCheck
tst.l fcolor(a6)
bne @CheckColorizeNOPDone ;fcolor not a NOP for direct device
move.l bcolor(a6),d1 ;is fg color a NOP?
lea NOPfgColorTable,a0
cmp.l (a0,d4*4),d1
bne @CheckColorizeNOPDone
bra.s @ClearColorizeBits ;it's a NOP, clear the colorize bits
@DeepSrc
;
; if swapfgbgBit is set, we need to swap RGB fg/bg color
;
move.w d0,XLateFlag(a6) ;save translation flags
btst #swapfgbgBit,XLateFlag+1(a6) ;rgb invert?
beq.s @DontSwap ;don't invert
PEA RGBBgColor(a6)
PEA RGBFrColor(a6) ;get fg color for colorizing
bra.s @SwapDone
@DontSwap
PEA RGBFrColor(a6) ;get fg color for colorizing
PEA RGBBgColor(a6)
@SwapDone
_GetBackColor ;get bg color for colorizing
_GetForeColor
;
; convert 16-16-16 to 8-8-8 for 32-bit src (D3=5)
;
cmp.w #4,d3 ;16-bit src?
beq.s @ConvertTo555 ;yes, convert to 555
move.l RGBBgColor(a6),d0 ;get RRRRGGGG
lsr.l #8,d0 ;get 00RRRRGG
lsl.w #8,d0 ;put green where it belongs, now 00RRGG00
move.b RGBBgColor+4(a6),d0 ;get blue: 00RRGGBB
move.l d0,RGBBgColor(a6)
move.l RGBFrColor(a6),d0 ;get RRRRGGGG
lsr.l #8,d0 ;get 00RRRRGG
lsl.w #8,d0 ;put green where it belongs, now 00RRGG00
move.b RGBFrColor+4(a6),d0 ;get blue: 00RRGGBB
move.l d0,RGBFrColor(a6)
move.w XLateFlag(a6),d0 ;get translation flags
;
; if RGBFrColor and RGBBgColor are white and black, colorizing is a nop so clear
; ColorizeInSrcBufBit. This is backwards from normal since it is a direct device.
;
tst.l RGBFrColor(a6) ;is Fr color black, ie a NOP for colorizing?
bne.s @CheckColorizeNOPDone ;no, colorizing is not a nop
cmp.l #$00FFFFFF,RGBBgColor(a6) ;is bg color white ($00FFFFFF) (a NOP)
bne.s @CheckColorizeNOPDone
@ClearColorizeBits
and.w #~(ColorizeInSrcBuf+ScaleColor),d0 ;turn off SrcBuf and scale case colorizing
bra.s @CheckColorizeNOPDone
;
; convert 16-16-16 to 5-5-5 for 16-bit src (D3=4)
;
@ConvertTo555
moveq #0,d0 ;clear alpha
move.w RGBBgColor(a6),d0 ;get RRRR
lsl.l #5,d0 ;put correct red in high word
move.w RGBBgColor+2(a6),d0 ;get GGGG
lsl.l #5,d0 ;put correct green in high word
move.w RGBBgColor+4(a6),d0 ;get BBBB
lsl.l #5,d0 ;put correct blue in high word
swap d0
move.w d0,RGBBgColor(a6)
move.w d0,RGBBgColor+2(a6)
moveq #0,d0 ;clear alpha
move.w RGBFrColor(a6),d0 ;get RRRR
lsl.l #5,d0 ;put correct red in high word
move.w RGBFrColor+2(a6),d0 ;get GGGG
lsl.l #5,d0 ;put correct green in high word
move.w RGBFrColor+4(a6),d0 ;get BBBB
lsl.l #5,d0 ;put correct blue in high word
swap d0
move.w d0,RGBFrColor(a6)
move.w d0,RGBFrColor+2(a6)
;
; if RGBFrColor and RGBBgColor are white and black, colorizing is a nop so clear
; ColorizeInSrcBufBit. This is backwards from normal since it is a direct device.
;
move.w XLateFlag(a6),d0 ;save translation flags
tst.l RGBFrColor(a6) ;is Fg color black, ie a NOP for colorizing?
bne.s @CheckColorizeNOPDone ;no, colorizing is not a nop
cmp.l #$7FFF7FFF,RGBBgColor(a6) ;is bg color white ($00FFFFFF) (a NOP)
bne.s @CheckColorizeNOPDone
and.w #~(ColorizeInSrcBuf+ScaleColor),d0 ;turn off SrcBuf and scale case colorizing
@CheckColorizeNOPDone
move.w d0,XLateFlag(a6) ;save translation flags
btst #InvertItBit,XLateFlag+1(a6) ;TEST INVERT BIT
SNE D7 ;set byte flag in d7
EXTB.L D7 ;INVERTED; D7 GETS ALL 1'S
LEA NOPfgColorTable,A0 ;get address of white table <42>
AND.L 0(A0,D4.W*4),D7 ;remove alpha byte/bit from mask <42>
MOVE.L D7,INVERTFLAG(A6) ;SAVE INVERT FLAG
BRA.S NOTPAT ;=>NO, USE SOURCE INSTEAD
;------------------------------------------------------------------
;
; PATTERN WILL BE USED. EXPAND PATTERN TO THE CURRENT DEPTH.
;
DoPattern
MOVEQ #0,D7 ;if mode is arithmetic, use 0 for <SMC 18SEP90>
BTST #5,D2 ; the ivert flag and skip bit 2 clear <SMC 18SEP90>
BNE.S @notnot ; <SMC 18SEP90>
BCLR #2,D2 ;TEST AND CLR INVERT BIT
SNE D7 ;set byte flag in d7
EXTB.L D7 ;INVERTED; D7 GETS ALL 1'S
@notnot MOVE.L D7,INVERTFLAG(A6) ;SAVE INVERT FLAG <SMC 18SEP90>
; move.w d2,locMode(a6) ;store for modecase, BitBlt, RgnBlt
_PATEXPAND ;EXPAND PATTERN
;----------------------------------------------------
;
; HIDE THE CURSOR IF TO THE SCREEN AND INTERSECTS MINRECT
; (A5 must contain global ptr)
;
NOTPAT
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
BEQ.S NOTSCREEN ;=>NO
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
_SHIELDCURSOR ;REMOVE CURSOR IF INTERSECT
NOTSCREEN
;----------------------------------------------------------------
;
; SET UP SRC ROWBYTES, MASK ROWBYTES, AND DST ROWBYTES
; GET SRCPIX INTO A4 AND DSTPIX INTO A5
; GET SRCRECT INTO A2 AND DSTRECT INTO A3
;
LEA SRCPIX(A6),A4 ;POINT TO SRCPIX
MOVE #nuRBMask,D0 ;GET MASK FOR ROWBYTE FLAGS
EXT.L D0 ;MAKE IT LONG
MOVE ROWBYTES(A4),D1 ;GET SRC ROWBYTES
AND.L D0,D1 ;CLEAR OUT FLAG BITS
MOVE.L D1,SRCROW(A6) ;SRCROW := SRC ROWBYTES
@1 LEA MASKPIX(A6),A0 ;POINT TO MASKPIX
MOVE ROWBYTES(A0),D1 ;GET DST ROWBYTES
AND.L D0,D1 ;CLEAR OUT FLAG BITS
MOVE.L D1,MASKROW(A6) ;MASKROW := MASK ROWBYTES
LEA DSTPIX(A6),A5 ;POINT TO DSTPIX
MOVE ROWBYTES(A5),D1 ;GET DST ROWBYTES
AND.L D0,D1 ;CLEAR OUT FLAG BITS
MOVE.L D1,DSTROW(A6) ;DSTROW := DST ROWBYTES
MOVE.L srcRect(a6),a2 ;get srcRect 24 bit ptr @@@@ BAL 12Jan89
MOVE.L a2,d0 ;get srcRect ptr @@@@ BAL 09Apr88
_rTranslate24To32
move.l d0,srcRect(a6) ;save 32 bit ptr @@@@ BAL 07Jul88
MOVE.L dstRect(a6),a3 ;get dstRect 24 bit ptr @@@@ BAL 12Jan89
MOVE.L a3,d0 ;get dstRect ptr @@@@ BAL 09Apr88
_rTranslate24To32
move.l d0,dstRect(a6) ;save 32 bit ptr @@@@ BAL 07Jul88
;----------------------------------------------------------------
;
; IF PATTERN MODE, GO DECIDE BETWEEN RGNBLT AND BITBLT
;
MOVE LOCMODE(A6),D0 ;GET MODE
ROR #4,D0 ;IS PATTERN BIT SET ?
BCS NOTSTR ;=>YES, DON'T USE STRETCH
;----------------------------------------------------------------
;
; CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT.
; IF NUMER = DENOM AND SRC DEPTH = DST DEPTH THEN JUST CALL RGNBLT.
;
MOVE BOTTOM(A2),D1
SUB TOP(A2),D1 ;CALC SRC HEIGHT
SWAP D1 ;PUT IN HI WORD
MOVE RIGHT(A2),D1
SUB LEFT(A2),D1 ;CALC SRC WIDTH
MOVE D1,D0 ;COPY SRC PIXCNT
SUBQ #1,D0 ;MAKE IT 0 BASED
MOVE D0,SRCPIXCNT(A6) ;SAVE SRC PIXEL COUNT
MOVE BOTTOM(A3),D0
SUB TOP(A3),D0 ;CALC DST HEIGHT
SWAP D0 ;PUT IN HI WORD
MOVE RIGHT(A3),D0
SUB LEFT(A3),D0 ;CALC DST WIDTH
_BlitCase ;Go determine blit style
;----------------------------------------------------------------
;
; Determine whether to use Stretch, Scale, Rgn, or Bit Bliting
;
BlitCase
clr.b FastCase(a6) ;assume not a fun case
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, ScaleColorBit, or ColorizeInSrcBufBit is set
;
move.w XLateFlag(a6),d2
and.w #~(UseStretch+ColorizeInSrcBuf),d2 ;use stretch? <05JUNE92 SAH>
cmp.w XLateFlag(a6),d2
bne Stretch ;
;
; Use ScaleBlt if ScaleColorBit is set <05JUNE92 SAH>
;
btst #ScaleColorBit,XlateFlag+1(a6)
bne xScaleBlt
CMP D3,D4 ;ARE THE DEPTHS THE SAME?
bne xScaleBlt ;=>no, use ScaleBlt
;
; source and destination are the same depth, check if color table seeds are the same
;
cmp #16,dstpix+pixelType(a6) ;is it a direct device?
beq.s notstr ;yes, don't check seeds
MOVE.L SRCPIX+PMTABLE(A6),d2 ;GET SRC COLOR TABLE HANDLE <BAL>
beq XScaleBLT ;nil table so must remap colors <BAL>
move.l d2,a0 ;get handle for deref <BAL>
MOVE.L (A0),A0 ;POINT TO IT
MOVE.L CTSEED(A0),D2 ;GET SEED
MOVE.L DSTPIX+PMTABLE(A6),A0 ;GET DST COLOR TABLE HANDLE
MOVE.L (A0),A0 ;POINT TO IT
CMP.L CTSEED(A0),D2 ;DO THE SEEDS MATCH?
BNE xScaleBlt ;=>NO, use scaleBlt
NOTSTR
;----------------------------------------------------------------
;
; NOW DECIDE BETWEEN BITBLT AND RGNBLT
;
; ARE ALL THREE REGIONS RECTANGULAR ? IF SO, USE BITBLT.
;
; If the visRgn or the clipRgn is non-rectangular then call TrimRect
; to see if the intersection of the region and MinRect is rectangular,
; empty, or regional. <C951> 08Nov87 BAL
;
MOVEQ #10,D0 ;GET SIZE OF RECT RGN
MOVE.L RGNC(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D0 ;IS RGNC RECTANGULAR ?
BNE XRGNBLT ;=>NO, USE RGNBLT
@chkVis MOVE.L RGNB(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D0 ;IS visRgn RECTANGULAR ? <C951>
BEQ.S @chkClip ;=>yes, go check clipRgn <C951>
MOVE.L RGNB(A6),-(SP) ;PUSH visRgn HANDLE <C951>
PEA MINRECT(A6) ;PUSH ADDR OF MINRECT
MOVE.W #-1,-(SP) ;pass Trim = True
_TRIMRECT ;CALL TRIMRECT
BLT DONE ;=>INTERSECTION EMPTY, QUIT & SHOW CURSOR
BGT XRGNBLT ;=>USE RGNBLT
; In case we fall into RgnBlt, replace visRgn with WideOpen
; so that TrimRect doesn't get called again by seekMask.
MOVE.L SAVEA5(A6),A1 ;Get global ptr <BAL 26Sep88>
MOVE.L GRAFGLOBALS(A1),A1 ;point to QD globals <BAL 26Sep88>
MOVE.L WIDEOPEN(A1),RGNB(A6) ;replace visRgn with wideOpen <BAL 26Sep88>
@chkClip
;
;<85>
; Force into rgnblt instead of bitblt if pattern hiliting. Both rgn and bitblt
; check for a fast, black pattern hiliting case in a stupid way. The problem
; is fixed in RgnBlt because it's near the top, but not in bitblt because it
; would mean patching out gobs of stuff. So, this slimey hack forces a call to
; rgnblt so the fast case is taken instead of the slow case in bitblt.
; If forcing into rgnblt, the clipRgn and userRgn are not swapped because we DO
; want TrimRect to get called in SeekMask.
;
CMP.W #58,LOCMODE(A6) ;pattern hilite mode? <85>
BEQ XRGNBLT ;yes, force into rgnblt <85>
MOVE.L RGNA(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D0 ;IS clipRgn RECTANGULAR ?
BEQ XBITBLT ;=>YES, GO USE BITBLT
MOVE.L RGNA(A6),-(SP) ;PUSH clipRgn HANDLE <C951>
PEA MINRECT(A6) ;PUSH ADDR OF MINRECT <C951>
MOVE.W #-1,-(SP) ;pass Trim = True
_TRIMRECT ;CALL TRIMRECT <C951>
BLT DONE ;=>INTERSECTION EMPTY, QUIT & SHOW CURSOR
BEQ XBITBLT ;=>USE BITBLT
; Since we will fall into RgnBlt, swap the clipRgn and the userRgn
; so that TrimRect doesn't get called again by seekMask.
MOVE.L RGNA(A6),A1 ;copy clipRgn <BAL 26Sep88>
MOVE.L RGNC(A6),RGNA(A6) ;replace clipRgn with userRgn <BAL 26Sep88>
MOVE.L A1,RGNC(A6) ;replace userRgn with clipRgn <BAL 26Sep88>
BRA XRGNBLT ;=>USE RGNBLT <BAL 26Sep88>
XScaleBLT
;--------------------------------------------------------------
;
; Must do depth scaling but no spatial resizing and no bit mask.
; Only supports copy and dither modes. No fg/bk colorizing.
; No search procs supported for direct sources.
;
; REGISTER USE:
;
; A2: SRCRECT (24 bit addr)
; A3: DSTRECT (24 bit addr)
; A4: SRCPIX
; A5: DSTPIX
;
; D3: SRCSHIFT
; D4: DSTSHIFT
; D7: INVERT FLAG
tst locMode(a6) ;copy mode?
bne Stretch ;if not copy mode then use stretch
;
; Use Stretch if an alpha mode is set by looking at the streamMode <23JUN92 SAH>
;
; Rather than looking at the stream mode directly here, we should add a call to the alpha
; routines that returns the alpha mode so that we can localize the code! Do this before it
; goes into ROM!
;
move.l savea5(a6),a0 ;get the real a5
move.l GrafGlobals(a0),a0 ;get the qd globals
move.l thePort(a0),a0 ;get the port
TST portBits+rowBytes(A0) ;is it an old port?
BPL @noalpha ;yes, alpha mode is illegal
MOVE.W dstPix+pixelSize(A6),D2 ;get depth of destination
CMP.W #16,D2 ;direct device?
BLT.S @noalpha ;no, skip this stuff
MOVE.L grafVars(A0),D2 ;get grafvars handle
BEQ @noalpha ;no grafvars, no alpha
MOVE.L D2,A0 ;copy handle
MOVE.L (A0),A0 ;dereference handle
BTST #PmNewGVBit-8,pmFlags(A0) ;make sure grafvars have been expanded
BEQ.S @noalpha ;if not, bail
TST.B streamMode(A0) ;is there an alpha mode
bne Stretch ;yes, so go slow
;
; now look at the actual alpha channel byte/bit to see if it contains zero. If not, we
; must go slow. This is because a streamMode of zero means that we write to both graphics
; and alpha. As an optimization, we might be able to just do this check alone for any
; streamMode so that we can go fast when writing an alpha of zero.
;
; For the purposes of Cube-E, this code is remaining as it is below, but it would be wise
; to make the tests just test memory directly to save code space!
;
MOVE.W dstPix+pixelSize(A6),D2 ;get depth of destination
cmp.w #16,d2 ;is dst 16 bit?
beq.s @check16bit ;yes
;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 Stretch ;if applying color then use stretch
tst.w d7 ;invert the src?
bne Stretch ;if so then use stretch
st FastCase(a6) ;remember fastCase for Andy
cmp.w #4,d4 ;dst < 16 bits/pixel? <05JUNE92 SAH>
blt.s @chkSrc ; <05JUNE92 SAH>
cmp.w #3,d3 ;src <16 bits/pixel?
bgt Stretch
@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 <08JUNE92 SAH>
;
; 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 <08JUNE92 SAH>
;
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 Stretch
cmp.w #3,d4 ;dst = 8 bits/pixel?
bne.s Stretch
bra.s @fast
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
move.w XLateFlag(a6), BGnotWhite(a6) ;BitBlt expects BGnotWhite to be setup
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
clr.w BGnotWhite(a6) ;assume bitblt can go fast
BTST #ColorizeInModeCaseBit, XLateFlag(a6) ;colorize?
BNE.S @slow ;no, continue
tst.l d7 ;inverting? <KON 6JUN90>
beq.s @fast ;no, go fast <KON 6JUN90>
@slow move.w #1,BGnotWhite(a6) ;tell bitblt to go slow
@fast _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
clr.w BGnotWhite(a6) ;assume rgnblt can go fast <98>
BTST #ColorizeInModeCaseBit, XLateFlag(a6) ;colorize? <98>
BEQ.S @fast ;no, continue <98>
move.w #1,BGnotWhite(a6) ;tell rgnblt to go slow <98>
@fast ; <98>
move.l stNoStackPtr,goShow(a6) ;pass go home routine to getSeek <BAL 21Mar89>
_StackAvail ;GET STACK AVAIL IN D0.L
LSR.L #2,D0 ;CONVERT BYTES TO LONGS
SUB.L #qdStackXtra/4,D0 ;SUBTRACT SLOP FACTOR <1.5> BAL
MOVE.L D0,STACKFREE(A6) ;AND SAVE FREE LONGS ON STACK
_RGNBLT ;CALL RGNBLT
BRA DONE ;RESTORE CURSOR AND QUIT
STRETCH
;
; if not shrinking and source is 1-bit b&w, clear dither flag <24Sept90 KON>
;
cmp.w d0,d1 ;compare dst(d0) and src(d1) widths
blt.s @dontClearDither ;if expanding, don't dither <27FEB90 KON>
cmp.l d0,d1 ;compare dst(d0) and src(d1) heights
blt.s @dontClearDither ;if expanding, don't dither <27FEB90 KON>
move.l srcpix+pmtable(a6),d2 ;get source color table handle <24Sept90 KON>
beq.s @dontClearDither ;nil table: not 1-bit <24Sept90 KON>
move.l d2,a0 ;get handle for deref <24Sept90 KON>
move.l (a0),a0 ;point to it <24Sept90 KON>
moveq #1,d2 ; <24Sept90 KON>
cmp.l ctseed(a0),d2 ;one-bit b&w? <24Sept90 KON>
bne.s @dontClearDither ; <24Sept90 KON>
clr.b useDither(a6) ;don't promote source to 32-bits <24Sept90 KON>
@dontClearDither
;----------------------------------------------------------------
;
; (If dither flag or mask is deep) AND source is indexed data then
; pretend the source is 32 bit/pixel RGB data and remember
; real depth/srcShift for later.
;
move.w d3,realSrcShift(a6) ;make it real anyway
st realDepth(a6) ;assume not promoting source to RGB
cmp.w #16,srcPix+pixelType(a6) ;is src direct?
beq @dontUseRGB ;yes, leave source depth alone
tst.b useDither(a6) ;is the dither bit set?
bne.s @UseRGB ;yes, promote source depth
move maskshift(a6),d2
beq.s @dontUseRGB
@UseRGB
move.w #16,srcPix+pixelType(a6) ;pretend direct data
move.w srcPix+pixelSize(a6),realDepth(a6)
move.w #32,srcPix+pixelSize(a6) ;pretend 32 bits/pixel
moveq #5,d3 ;reset src shift
move.w d3,srcShift(a6)
;
; if scalecase colorizing was used, change to srcbuf colorizing since the scale table
; is not used when the src is 32-bits. <12NOV90 KON>
;
bclr #ScaleColorBit,XLateFlag+1(a6) ;Colorize in scale table?
beq.s @NoColorizing ;no, we're cool
;
; colorizing -> change to srcbuf colorizing and setup RGBFrColor and RGBBgColor
;
bset #ColorizeInSrcBufBit,XLateFlag(a6) ;colorize at srcbuf time
movem.l A5/D0/D1,-(SP) ;Need to preserve a5, d0, and d1
move.l SAVEA5(A6),A5 ;restore 15 for GetFore and GetBack color calls
btst #swapfgbgBit,XLateFlag+1(a6) ;rgb invert?
beq.s @DontSwap ;don't invert
PEA RGBBgColor(a6)
PEA RGBFrColor(a6) ;get fg color for colorizing
bra.s @SwapDone
@DontSwap
PEA RGBFrColor(a6) ;get fg color for colorizing
PEA RGBBgColor(a6)
@SwapDone
_GetBackColor ;get bg color for colorizing
_GetForeColor
;
; convert 16-16-16 to 8-8-8 for 32-bit src (D3=5)
;
move.l RGBBgColor(a6),d0 ;get RRRRGGGG
lsr.l #8,d0 ;get 00RRRRGG
lsl.w #8,d0 ;put green where it belongs, now 00RRGG00
move.b RGBBgColor+4(a6),d0 ;get blue: 00RRGGBB
move.l d0,RGBBgColor(a6)
move.l RGBFrColor(a6),d0 ;get RRRRGGGG
lsr.l #8,d0 ;get 00RRRRGG
lsl.w #8,d0 ;put green where it belongs, now 00RRGG00
move.b RGBFrColor+4(a6),d0 ;get blue: 00RRGGBB
move.l d0,RGBFrColor(a6)
movem.l (SP)+,a5/D0/D1 ;Restore a5,d0, and d1
@NoColorizing
@dontUseRGB
;-----------------------------------------------------------------------
; Change source pixel size to 32 bits if deep mask and src is 16-bit
;
cmp #4,d3 ;is it 16 bit?
bne.s KON
tst.w maskshift(a6)
beq.s KON
moveq #5,d3
KON
;----------------------------------------------------------------
;
; USE SRC AND DST SIZES TO DETERMINE STRETCHING ROUTINE
;
MOVE.L D0,NUMER(A6) ;NUMER := DST SIZE
MOVE.L D1,DENOM(A6) ;DENOM := SRC SIZE
MOVEM.L D3/D4,-(SP) ;SAVE D3/D4
_SetupStretch ;CALC CASEJUMP AND HORIZ FRACT (CLOBBER D3,D4)
MOVE.L A0,RATIOCASE(A6) ;SAVE CASE JUMP FOR LATER
MOVE D0,HORIZFRACTION(A6) ;SAVE FRACTION FOR LATER
MOVEM.L (SP)+,D3/D4 ;RESTORE D3/D4
clr.l SrcPixPmTable(a6) ; <KON 13DEC90>
MOVE.L SRCPIX+PMTABLE(A6),d0 ;GET SRC COLOR TABLE HANDLE <2Sep90 KON>
beq.s @BAL ;table not nil so continue <2Sep90 KON>
MOVE.L d0,a0
MOVE.L (A0),d0 ;POINT TO IT <2Sep90 KON>
_rTranslate24To32 ;clean master pointer <20AUG90 KON and BAL>
move.l d0,SrcPixPmTable(a6) ; <20AUG90 KON and BAL>
@BAL
;----------------------------------------------------------------
;
; DETERMINE AMOUNT OF STACK SPACE WE CAN USE
; Raised amount left for interupts from 1024 to 1600 bytes <BAL 10Apr89>
;
_StackAvail ;GET STACK AVAIL IN D0.L
LSR.L #2,D0 ;CONVERT BYTES TO LONGS
SUB.L #qdStackXtra/4,D0 ;SUBTRACT SLOP FACTOR <1.5> BAL
MOVE.L D0,STACKFREE(A6) ;AND SAVE FREE LONGS ON STACK
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
;----------------------------------------------------------------
;
; Check to see if we are shrinking 16 or 32 bit source data OR if we are
; shrinking a deep mask. If we are, allocate a buffer for the larger of the
; two. *** Currently assuming source and mask are the same size ***
;
clr.b useAverage(a6) ;assume not averaging
move.w numer+v(A6),D0 ; get destination height
move.w denom+v(A6),D1 ; get source height
cmp.w d1,d0 ;is source larger than dest?
bge.s @noAvrg ;NO=> don't average
;yes, so average if 32 bit/pixel or deep mask
cmp.w #4,d3 ;is src indexed? <KON 2/22/90>
blt.s @noAvrg ;yes, skip averaging <KON 2/22/90>
@shrink
sge useAverage(a6) ;always average if 16 or 32bit src <KON 2/22/90>
moveq #0,d1
move.w denom+h(a6),d1 ;src width
move.l d1,d2 ;make a copy src width <16Feb90 KON and BAL>
add.l d2,d2 ;6 bytes (R.w,G.w,B.w) per pixel <BAL and KON 14Feb90>
add.l d1,d2 ;d2 is byte cnt/2 of AvrgBuf <BAL and KON 14Feb90>
;
; allocate the larger of source buffer or mask buffer
;
cmp.w #4,maskshift(a6) ;mask 16-bit data?
beq.s @DoWords ;yes, allocate twice the error buffer
; cmp.w #4,d3 ;source 16-bit data? <KON 2/22/90>
cmp.w #4,realSrcShift(a6) ;source 16-bit data (check real source)? <KON 3/18/91>
beq.s @DoWords ;Twice as many pixels, allocate twice the error buffer <KON 2/22/90>
lsr.l #1,d2 ;both 32-bit, 1/2 as many pixels
@DoWords
move.w d2,ABufSize(a6) ;save long cnt for later
SUB.L D2,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK2
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK2
CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP
@ClrBuf CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D2,@ClrBuf ;LOOP ENTIRE BUFFER
MOVE.L SP,AvrgBuf(A6) ;REMEMBER WHERE AvrgBuf IS
@noAvrg
;----------------------------------------------------------------
;
; if dstPix is direct and we aren't averaging then no
; reason to promote source to RGB, unless using deep mask.
;
tst.b realDepth(a6) ;promoting src to RGB?
bmi.s @LeaveItAlone ;no, all ok
cmp.w #16,dstPix+pixelType(a6) ;is dst direct data?
bne.s @LeaveItAlone ;no, we will be dithering
tst.b useAverage(a6) ;are we averaging
bne.s @LeaveItAlone ;yes, promote source
tst.w maskshift(a6) ;deep mask?
bne.s @LeaveItAlone ;yes: promote
;
;no, don't promote source
;
move.w realDepth(a6),srcPix+pixelSize(a6)
move.w realSrcShift(a6),d3 ;don't fake 32-bit source
move.w d3,srcShift(a6) ;remember it for later
st realDepth(a6) ;don't expand source to 32-bit
clr.w SRCPIX+pixelType(A6) ;don't fake
;
; Change colorizing back to Scalecase colorizing since the scale table
; is used for indexed sources. <12NOV90 KON>
;
bclr #ColorizeInSrcBufBit,XLateFlag(a6) ;colorize at srcbuf time?
beq.s @NoColorizing ;no, we're cool
;
; colorizing -> change back to scalecase colorizing
;
bset #ScaleColorBit,XLateFlag+1(a6) ;Colorize in scale table
@NoColorizing
@LeaveItAlone
;----------------------------------------------------------------
;
; IF THE SRC AND DST ARE DIFFERENT DEPTHS, THEN MUST DO PIXEL SCALING
; IF THEY ARE THE SAME DEPTH, BUT DIFFERENT COLOR TABLES, DO PIXEL SCALING
;
CLR.L SCALECASE(A6) ;ASSUME NO PIXEL DEPTH SCALING
MOVE.W SRCPIX+pixelType(A6),D0 ;IS PIXELTYPE DIRECT? %%%
BEQ HasClut ;NO, IT HAS A CLUT %%%
cmp #16,d0 ;is it RGBDirect?
bne done ;unknown pixeltype -> go home
;@@@@ should also check cmpCount, cmpSize
MOVE.L ([theGDevice]),A2 ; get the current device (trash A2)
tst.l gdSearchProc(A2) ; get the search proc head
bne.s @Slow
cmp d3,d4 ;are the depths the same
beq PIXELOK ;yes, don't depth scale
;----------------------------------------------------------------
;
; The src is direct data (16 or 32 bits/pixel).
; Compute D5 as index into direct mode table based on
;
; src16 -> add 4
; dstIndexed -> add 1
; searchProc -> add 16
; dithering -> add 2
; dst16 -> add 2
; dstAllGray -> add 8
;
; D3=srcShift D4=dstShift
;
@Slow
moveq #4,d0 ; init direct scaleRtn with src=16
move.l d0,d5
cmp.w d3,d5 ; is src 16 bits/pixel?
beq.s @src16
moveq #0,d5 ; init src to 32 bits/pixel
@src16
cmp.w d4,d0 ; is dst 16 bits/pixel?
bne.s @dst32
addq #2,d5 ; remember dst is 16 bits/pixel
@dst32
cmp #16,DSTPIX+pixelType(A6) ;IS PIXELTYPE DIRECT? %%%
beq @noCLUT ;don't makeItable on direct device
; IF THE DST IS AN OLD GRAFPORT AND ONE BIT PER PIXEL, THEN OVERRIDE THE
; scaleCase FOR PROPER MAPPING
TST d4 ;ONE BIT PER PIXEL?
BNE.S @notBitmap ;=>NO, PROC IS OK
MOVE.L DSTBITS(A6),A1 ;GET DST BITMAP
TST ROWBYTES(A1) ;IS IT OLD?
BMI.S @notBitmap ;=>NO, PROC IS OK
addq #8,d5 ;force bitmap procs
bra @chkDither ;go check dither <BAL 28Jan90>
@notBitmap
addq #1,d5 ; remember dst is indexed
MOVE.L ([GDPMap,A2]),A1 ; get pixMap's handle
MOVE.L PMTable(A1),A0 ; get the device colorTable's handle
MOVE.L ([A0],CTSeed),D1 ; get the device colorTable's ctSeed
MOVE.L ([GDITable,A2]),A0 ; get the Itable's master pointer
CMP.L ITabSeed(A0),D1 ; has the colortable changed?
BEQ.S @1 ; if equal, then the iTable is OK
; if table is not up to date, build a new one
MOVE.L PMTable(A1),-(SP) ; push theGDevice's color table handle <BAL 26May89>
MOVE.L GDITable(A2),-(SP) ; push theGDevice's current iTabHandle
MOVE.W GDResPref(A2),-(SP) ; push the preferred iTableResolution
_MakeITable ; make a new table
TST.W QDErr ; was this sucessful?
BEQ.S @noErr ; nope, so quit
ADDQ #4,SP ; flush saved register
BRA doneErr ; <BAL 26May89>
@noErr MOVE.L ([theGDevice]),A2 ; redereference in case it moved <BAL 31Mar89>
MOVE.L ([GDITable,A2]),A0 ; get the iTable's master pointer
@1
ADD.w #ITTable,A0 ; point directly at data
MOVE.L A0,stITabPtr(A6) ; save in stack frame
SUB.w #ITTable,A0 ; get the iTable's master pointer
MOVE.W ITabRes(A0),stITabRes(A6) ; get the iTable resolution
MOVE.L ([GDPMap,A2]),A1 ; get pixMap's handle
MOVE.L ([PMTable,A1]),stCLUTPtr(A6) ; get the device colorTable's ptr
MOVE.L gdSearchProc(A2),D0 ; get the search proc head
bne.s @search ; go use search routines
; Here we know that the dst is indexed and no search proc is present,
; so determine if the dst clut is all grays and/or we are dithering.
; the iTable's master pointer is in A0
MOVEQ #1,D0 ; prime the register again
MOVE ITabRes(A0),D2 ; get the inverse table resolution (and Bit-field width)
LSL.L D2,D0 ; calculate 2^^res
LSL.L D2,D0 ; square it
LSL.L D2,D0 ; cube it
LEA ITTable(A0,D0.L),A1 ; point us at the ITabInfo
tst.w iTabFlags(a1) ; is this a grayITab?
bpl.s @chkDither ; no, go see if dithering
add.w #ITabInfo,a1 ; point past header
move.l a1,stITabInfo(a6) ; save for later
addq #8,d5 ; remember to use gray routines
moveq #40,d0
cmp.l ITabSeed(a0),d0 ; is dst the standard 8-bit gray clut?
beq.s @readyProc ; yes, ignore dithering for speeed!
@chkDither
tst.b useDither(a6) ; should we dither?
beq.s @readyProc ; no, we're set
addq #2,d5 ; remember to use dither routines
;
; Compute and allocate scanline buffer for dither error from previous scan <BAL 29Aug88>
;
MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0
MOVE NUMER+H(A6),D0 ;GET WIDTH OF DST
lsl.l d4,d0 ;get bit width
add.l #31,d0 ;round to long boundary
lsr.l d4,d0 ;get adjusted pixel width
btst #3,d5 ;is dst a grayscale clut?
bne.s @gray ;only need 2 bytes per pixel for gray error <BAL 18Mar89>
move.l d0,d1 ;make a copy <BAL and KON 14Feb90>
ADD.l D0,D0 ;6 bytes (R.w,G.w,B.w) per pixel <BAL and KON 14Feb90>
add.l d1,d0 ;d0 is byte cnt/2 of ErrBuf <BAL and KON 14Feb90>
@gray LSR.l #1,D0 ;AND DIV BY 2 FOR LONGS <BAL and KON 14Feb90>
SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK3
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK3
CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP
@ClearB CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,@ClearB ;LOOP ENTIRE BUFFER
MOVE.L SP,ErrBUF(A6) ;REMEMBER WHERE ErrBuf IS
clr.b ErrDir(a6) ;init to carry error to right
BRA.S @readyProc ; and continue
; Here we know that the dst is direct so check if search proc is present.
@noCLUT
MOVE.L gdSearchProc(A2),D0 ; get the search proc head
beq.s @readyProc
@search
MOVE.L D0,stSProc(A6) ; put search procs list head in stack frame
bset #4,d5 ; use search routines
; We have the scaleCase routine selector in D5 so compute address
; of routine and stuff it in scaleCase for later
@readyProc
move.w d5,d0 ;copy selector
lsr.w #3,d0 ;determine table to use
lea (stColorTabPtr,ZA0,d0*4),A0 ;POINT TO MODE TABLE
move.l (a0),a0 ;get table
and.w #7,d5 ;get position in this table
add.l 0(A0,D5*4),A0 ;GET CASE JUMP ADDRESS
MOVE.L A0,scaleCase(A6) ; put depth scaling routine in stack frame
BRA PIXELOK ;=>ALREADY GOT ROUTINE
;----------------------------------------------------------------
;
; The src is indexed data (1,2,4,8 bits/pixel).
; If seeds don't match or depths are different then make a scale table.
; Special case 1-bit source.
;
HasClut
MOVE.L SRCPIX+PMTABLE(A6),d0 ;GET SRC COLOR TABLE HANDLE <BAL>
beq.s DOXLATE ;table not nil so continue <BAL>
move.l d0,a0 ;get handle for deref <BAL>
MOVE.L (A0),a0 ;POINT TO IT
MOVE.L CTSEED(A0),D0 ;GET SEED
MOVE.L DSTPIX+PMTABLE(A6),A0 ;GET DST COLOR TABLE HANDLE
cmp #16,DstPix+pixelType(a6) ;is it a direct device?
beq.s @chk1 ;yes, don't check seeds
MOVE.L (A0),A0 ;POINT TO IT
CMP.L CTSEED(A0),D0 ;DO THE SEEDS MATCH?
BNE.S @chk1 ;=>NO, MUST TRANSLATE
CMP D3,D4 ;DOES SRC DEPTH = DST DEPTH?
bne.s @chk1 ;no, then scale pixels
;
; check fg and bk color and if they aren't black and white
; then take chk1 case, otherwise, take pixelok case.
;
; <KON 5MAR91> begins here... This fixes a problem with drawing to bitmaps. The problem
; is when the main device is direct and the app sets the fg color to black and the
; bg color to white, we think we are colorizing since the sense of what is black and
; what is white is reversed. This can only happen when the destination pixmap is
; 1-bit and the destination GDevice is a direct device. Thus, I special case this
; situation and check the fg and bg colors for black and white correctly. There is
; probably a more elegant fix for this, but with 7.0 ready to ship this implementation
; causes the least risk since it should effect only the case we are interested in. If
; it's not this particular case, we branch to @OldWay and processing continues as before.
; YUK!
;
; if destination device is direct, and dst pixmap 1-bit bcolor = FFFFFFFF and
; fcolor = 0 is NOP
; else, bcolor = 0, fcolor = $FFFFFFFF is NOP
;
tst 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.l #1,d1
beq PIXELOK ;bk white, fg black, go fast
bra.s @chk1
; <KON 5MAR91> ends here...
@OldWay
move.l bcolor(a6),d1
bne.s @chk1 ;fg not black, go slow
move.l fcolor(a6),d1
addq.l #1,d1 ; <KON 6MAR91>
beq PIXELOK ;bk white, fg black, go fast
@chk1 TST D3 ;IS SRC ONE BIT PER PIXEL?
BNE.S DOXLATE ;=>NO, Build mapping table
MOVEQ #1,D1 ;GET CTSEED FOR DEFAULT ONE BIT TABLE
CMP.L D0,D1 ;IS IT THE DEFAULT?
BEQ SRCONE ;=>YES, USE EXPAND TABLES FOR SPEED
DOXLATE MOVE SRCPIX+PIXELSIZE(A6),D1 ;GET SRC BITS PER PIXEL
MOVEQ #1,D0 ;# ENTRIES = 2^ PIXELSIZE
LSL D1,D0 ;CALC # ENTRIES
SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
; IF THE DST IS AN OLD GRAFPORT AND IS ONE BIT PER PIXEL, THEN OVERRIDE THE
; SEARCH PROC FOR PROPER MAPPING
MOVEQ #0,D7 ;ASSUME NO PROC INSTALLED
CMP #1,DSTPIX+PIXELSIZE(A6) ;ONE BIT PER PIXEL?
BNE.S @PROCOK ;=>NO, PROC IS OK
MOVE.L DSTBITS(A6),A1 ;GET DST BITMAP
TST ROWBYTES(A1) ;IS IT OLD?
BMI.S @PROCOK ;=>NO, PROC IS OK
MOVEQ #1,D7 ;FLAG PROC INSTALLED
PEA ONEBITPROC ;POINT TO OUR PROC
_ADDSEARCH ;AND INSTALL IT
@PROCOK MOVE.L SAVEA5(A6),A5 ;GET A5 FOR MAKESCALETBL
MOVE.L A4,-(SP) ;PUSH SRCPIX POINTER
;
; If bit 0 = 1, then MakeScaleTbl colorizes, otherwise it don't.
; if mode is BIC or OR, then don't colorize in MakeScaleTbl
;
MOVE.w XLateFlag(a6),-(SP) ;pass arithmetic mode to get fg/bg relative colors
_MakeScaleTbl ;AND MAKE PIXEL TRANSLATION TABLE
;------------------------------------------------------------------------------------------
;
; <C947> 08Nov87 BAL begins here:
;
;------------------------------------------------------------------------------------------
;
; MakeScaleTbl is called whenever the src and dst pixmaps have different
; pixel depths or different color table seeds. MakeScaleTbl returns a
; pixel translation table used to map each src pixel to a dst pixel.
;
; Here I check to see if the translation table returned by MakeScaleTbl is in
; actuality an identity mapping--in which case no mapping at all is required!
; In order for an identity mapping to result the src and dst pixMaps must be of the same
; depth.
;
; If an identity mapping is detected, I must decide whether a stretch blit loop is
; really required (ie src rect ≠ dst rect or maskBits ≠ nil) or whether a much faster
; region blit or bit blit loop would suffice.
;
;------------------------------------------------------------------------------------------
move SRCPIX+PIXELSIZE(A6),d1 ;get src bits/pixel
cmp DSTPIX+PIXELSIZE(A6),d1 ;is it the same as dst bits/pixel?
bne.s @ScaleOK ;no, have to do pixel scaling
;inspect scale table for equality
@chkTbl MOVEQ #1,D0 ;# ENTRIES = 2^ PIXELSIZE
LSL D1,D0 ;CALC # ENTRIES in d0
move d0,d1 ;make a copy of long count
lsl #2,d1 ;get size of table
subq #1,d0 ;make counter zero based for dbra
move.l sp,a0 ;point to scale tbl
add d1,a0 ;point past end of table
@1 cmp.l -(a0),d0 ;compare with dst pixel value
dbne d0,@1
bne.s @ScaleOK ;tables are not equal so perform pixel scaling
CLR.L ScaleCase(a6) ;remember no pixel xlation needed <BAL 09Apr90>
MOVE.L SP,ScaleTbl(A6) ;SAVE TRANSLATION TABLE just in case <BAL 09Apr90>
;if we installed a proc get rid of it before short circuiting stretch
TST D7 ;DID WE INSTALL A PROC
BEQ.S @NOPRC ;=>NO, DON'T NEED TO REMOVE
PEA ONEBITPROC ;ELSE PUSH OUR PROC
_DELSEARCH ;AND DELETE IT
@NOPRC LEA DSTPIX(A6),A5 ;RESTORE DSTPIX POINTER
TST.L MASKBITS(A6) ;*** IS THERE A MASK?
BNE PIXELOK ;=>YES, USE STRETCH BUT DON'T PIXEL TRANSLATE
;----------------------------------------------------------------
;
; CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT.
; IF NUMER = DENOM AND SRC DEPTH = DST DEPTH THEN JUST CALL RGNBLT.
;
MOVE.L NUMER(A6),D0 ;GET WIDTH,HEIGHT OF DST
CMP.L DENOM(A6),D0 ;SAME AS WIDTH,HEIGHT OF SRC?
BNE PIXELOK ;no, must call stretch
MOVE.L INVERTFLAG(A6),D7 ;restore invert flag <<C983>>
BRA NOTSTR ;jump back and decide between bitblt and rgnblt
;don't really have to use stretch at all!
;------------------------------------------------------------------------------------------
;
; <C947> 08Nov87 BAL ends here.
;
;------------------------------------------------------------------------------------------
@ScaleOK
MOVE.L SP,ScaleTbl(A6) ;SAVE POINTER TO TRANSLATION TABLE
LEA DSTPIX(A6),A5 ;RESTORE DSTPIX POINTER
TST D7 ;DID WE INSTALL A PROC
BEQ.S @NOPROC ;=>NO, DON'T NEED TO REMOVE
PEA ONEBITPROC ;ELSE PUSH OUR PROC
_DELSEARCH ;AND DELETE IT
@NOPROC move.l stIndexedSrc,A0 ;POINT TO THE SCALING ROUTINE
MOVE.L A0,SCALECASE(A6) ;AND SAVE CASE JUMP FOR LATER
BRA PIXELOK ;=>ALREADY GOT ROUTINE
ALIGN Alignment
ONEBITPROC
;----------------------------------------------------------------
; FUNCTION ONEBITPROC(MYCOLOR:RGBCOLOR; VAR INDEX: LONG): BOOLEAN;
;
; THIS IS A COLOR MANAGER CUSTOM SEARCH PROC THAT MAPS RGB TO
; BLACK AND WHITE FOR MAPPING TO OLD GRAFPORTS.
; Algorithm modified to use [5 9 2] luminance mapping. <BAL 30Mar89>
;
MYINDEX EQU 4
MYRGB EQU 8
RESULT EQU 12
ST.B RESULT(SP) ;ALWAYS RETURN TRUE
MOVE.L MYRGB(SP),A0 ;POINT TO RGB
moveq #0,d0 ;clear out high end
moveq #0,d1 ;clear out high end
move.w red(a0),d0 ;get red
move.l d0,a1 ;keep red in a1
move.w green(a0),d1 ;get green
add.l d0,d1 ;accumulate luminance in d1
move blue(a0),d0
add.l d0,d1 ;accumulate luminance in d1
add.l d0,d1 ;accumulate luminance in d1
lsr.l #2,d1
add.l a1,d1 ;accumulate luminance in d1
move green(a0),d0
add.l d0,d1 ;accumulate luminance in d1
add.l d0,d1 ;accumulate luminance in d1
lsr.l #2,d1
MOVE.L MYINDEX(SP),A1 ;POINT TO INDEX
CLR.L (A1) ;ASSUME INDEX = WHITE
tst d1 ;check luminance
BMI.S @RESOK ;=>IF >= $8000 THEN WHITE
ADDQ.L #1,(A1) ;ELSE RETURN BLACK
@RESOK RTD #8 ;STRIP PARAMS AND RETURN
ALIGN Alignment
;
; loops that do colorizing, ptch versions destroy a3
;
ColorExTblPtr
DC.L ONEColor-ColorExTblPtr ;Need 1-bit colorizing <10Sept90 KON>
DC.L DOUBLEColor-ColorExTblPtr
DC.L QUADColor-ColorExTblPtr
DC.L EIGHTColor-ColorExTblPtr
DC.L SIXTEENColor-ColorExTblPtr
DC.L THRTWOColor-ColorExTblPtr
;
; One bit to N-bit colorizing loops
;
ALIGN Alignment
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 it out
DBRA D1,@a
RTS
ALIGN Alignment
DoubleColor
leaROM ciROMTable2,a3 ;get address of doubling table <30JUL90 KON>
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 0(a3,D0*2),d2 ;convert to 2-bit <30JUL90 KON>
;
;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
ALIGN Alignment
;
; One bit to 4-bit colorizing
;
QUADColor
leaROM ciROMTable4,a3 ;get address of quad table <30JUL90 KON>
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 0(a3,D0*4),D2 ;convert to 4 bits/pixel <30JUL90 KON>
;
;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
ALIGN Alignment
;-----------------------------------------------
;
; SCALE UP BY EIGHT USING TABLE LOOKUP, then colorize
;
EIGHTColor
leaROM ciROMTable8,a3 ;get address of eight table <30JUL90 KON>
move.l fcolor(a6),d3
move.l bcolor(a6),d4
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 (a3,D1),d2 ;get four pixels
AND #$0F,D0 ;MASK FOR LO NIBBLE
MOVE.L (a3,D0*4),D0 ;get second set of four pixels <30JUL90 KON>
;
;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
ALIGN Alignment
;-------------------------------------------------
;
; SCALE UP BY 16 (thanks to Gary Davidian)
; with colorizing
;
BWtoD15Alpha
MOVE.L alphaFore(A6),D3
MOVE.L alphaBack(A6),D4
BRA.S XXSIXTEEN
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)
;
BWtoD24Alpha
MOVE.L alphaFore(A6),D3
MOVE.L alphaBack(A6),D4
BRA.S XXTHRTWO
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
;----------------------------------------------------------------
;
; 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?
BLT.S @2 ;no, take normal path
MOVE.W locMode(A6),D0 ;get transfer mode
BTST #5,D0 ;arithmetic?
BNE.S @2 ;yes, take normal path
AND.W #3,D0 ;is the mode copy?
BEQ.S @2 ;yes, take normal path (because colors swapped)
MOVE.L alphaMask(A6),D1 ;get the alpha mask
TST.L INVERTFLAG(A6) ;are we inverting?
BEQ.S @1 ;no, leave invertflag alone
MOVE.L D1,INVERTFLAG(A6) ;yes, change invertflag to alphamask
@1: CLR.L alphaFore(A6) ;foreground is zeroes
MOVE.L D1,alphaBack(A6) ;background is alphamask
LEA @patchTable,A0
ADD.L -16(A0,D4*4),A0
BRA.S @gotScale ;jump to common code
@patchTable
DC.L BWtoD15Alpha-@patchTable
DC.L BWtoD24Alpha-@patchTable
@2: ;take normal path
;
;take special loops if colorizing
;
btst #ScaleColorBit,XLateFlag+1(a6) ;colorize in expansion?
beq.s @nocolorize ;no, colorize in blit loop
@colorize
lea ColorExTblPtr,a0
add.l (a0,d4*4),a0 ;colorize in expansion
;
; if swapfgbgBit is set, we need to swap fg/bg color again
;
bra.s @gotScale
@nocolorize
cmp.w #4,d4
blt.s @indexedDst
add.l 8(A0,D4*4),A0 ;choose between direct loops
bra.s @gotScale
@indexedDst
add.l 0(A0,D4*4),A0 ;USE DSTSHIFT TO SELECT ROUTINE
@gotScale
MOVE.L A0,SCALECASE(A6) ;SAVE CASE JUMP FOR LATER
;-----------------------------------------------------------------------
;
; We've got our ScaleCase.
;
PIXELOK
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR SRCBUF TO HOLD SRCWIDTH.
;
MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0
MOVE DENOM+H(A6),D0 ;GET WIDTH OF SRC
LSL.l D3,D0 ;SCALE WIDTH BY SRC DEPTH
SUBq.l #1,D0 ;SUBTRACT 1 BIT
LSR.l #5,D0 ;AND DIV BY 32 FOR LONGS
MOVE D0,SRCLONGS(A6) ;SAVE FOR LATER
SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT
CLRSRC CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLRSRC ;LOOP ENTIRE BUFFER
MOVE.L SP,SRCBUF(A6) ;REMEMBER WHERE SRCBUF IS
MOVE.L SP,DSTBUF(A6) ;ASSUME NO HORIZONTAL STRETCHING
MOVE.L SP,SCALEBUF(A6) ;ASSUME NO PIXEL TRANSLATION
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR DSTBUF TO HOLD DSTLONGS.
;
MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0
MOVE NUMER+H(A6),D0 ;GET WIDTH OF DST
CMP DENOM+H(A6),D0 ;SAME AS WIDTH OF SRC?
BEQ.S NOHSTRETCH ;=>YES, NO HORIZONTAL STRETCHING
LSL.l D3,D0 ;SCALE WIDTH BY SRC DEPTH
SUBq.l #1,D0 ;SUBTRACT 1 BIT
LSR.l #5,D0 ;AND DIV BY 32 FOR LONGS
MOVE D0,DSTLONGS(A6) ;SAVE FOR LATER
SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP
CLRDST CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLRDST ;LOOP ENTIRE BUFFER
MOVE.L SP,DSTBUF(A6) ;REMEMBER WHERE DSTBUF IS
MOVE.L SP,SCALEBUF(A6) ;DEFAULT SCALEBUF = DSTBUF
NOHSTRETCH
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR MASK TO HOLD srcMASKlongs.
;
CLR.L MASKNUMER(A6) ;SRC MASK WIDTH
CLR.L MASKDENOM(A6) ; = DST MASK WIDTH
MOVE.L MASKBITS(A6),D0 ;IS THERE A MASK?
BEQ NODST ;=>NO, DON'T ALLOCATE MASK BUFFERS
;----------------------------------------------------------------
;
; CALC NUMER AND DENOM BASED ON DSTRECT AND MASKRECT.
;
MOVE.L MASKRECT(A6),A0 ;POINT TO MASKRECT
MOVE BOTTOM(A0),D1
SUB TOP(A0),D1 ;CALC MASK HEIGHT
SWAP D1 ;PUT IN HI WORD
MOVE RIGHT(A0),D1
SUB LEFT(A0),D1 ;CALC MASK WIDTH
MOVE BOTTOM(A3),D0
SUB TOP(A3),D0 ;CALC DST HEIGHT
SWAP D0 ;PUT IN HI WORD
MOVE RIGHT(A3),D0
SUB LEFT(A3),D0 ;CALC DST WIDTH
;----------------------------------------------------------------
;
; USE MASK AND DST SIZES TO DETERMINE MASK STRETCHING ROUTINE
;
MOVEM.L D3/D4,-(SP) ;SAVE D3/D4
MOVE.L D0,MASKNUMER(A6) ;NUMER := DST SIZE
MOVE.L D1,MASKDENOM(A6) ;DENOM := SRC SIZE
_SetupStretch ;CALC CASEJUMP AND HORIZ FRACT (CLOBBER D3,D4)
MOVE.L A0,MASKCASE(A6) ;SAVE CASE JUMP FOR LATER
MOVE D0,MASKFRACT(A6) ;SAVE FRACTION FOR LATER
MOVEM.L (SP)+,D3/D4 ;RESTORE D3/D4
MOVEQ #0,D2 ;CLEAR HIGH WORD OF D0
move.w MASKDENOM+H(A6),d2 ;get width of mask
;
;unless depth = 1, depth promoted to 32 bit/pix
;
move.w maskshift(a6),d1
beq.s @onebitmask
move.l maskpix+pmTable(a6),a0
move.l (a0),d0 ;get pointer to color table <20AUG90 KON and BAL>
_rTranslate24To32 ;clean master pointer <20AUG90 KON and BAL>
move.l d0,MaskPixPmTable(a6) ; <20AUG90 KON and BAL>
moveq #5,d1
lsl.l d1,d2 ;scale width by mask depth
@onebitmask
SUB.l #1,D2 ;SUBTRACT 1 BIT
LSR.l #5,D2 ;AND DIV BY 32 FOR LONGS
MOVE D2,SRCMASKLONGS(A6) ;SAVE FOR LATER
SUB.L D2,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT
CLRMSK1 CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D2,CLRMSK1 ;LOOP ENTIRE BUFFER
MOVE.L SP,SRCMASKBUF(A6) ;REMEMBER WHERE SRCMASKBUF IS
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR DSTMASKBUF TO HOLD MASKLONGS.
;
MOVE.L SP,DSTMASKBUF(A6) ;ASSUME NO DSTBUF
MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0
MOVE MASKNUMER+H(A6),D0 ;GET WIDTH OF DST
CMP MASKDENOM+H(A6),D0 ;SAME AS WIDTH OF SRC?
BEQ.S NODST ;=>YES, NO DSTMASKBUF
;mask depth in d1 from above
lsl.l d1,d0 ;scale width by mask depth
@onebitmask
SUB.l #1,D0 ;SUBTRACT 1 BIT
LSR.l #5,D0 ;AND DIV BY 32 FOR LONGS
MOVE D0,DSTMASKLONGS(A6) ;SAVE FOR LATER
SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT
CLRMSK2 CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLRMSK2 ;LOOP ENTIRE BUFFER
MOVE.L SP,DSTMASKBUF(A6) ;REMEMBER WHERE DSTMASKBUF IS
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR SCALEBUF TO HOLD SCALELONGS.
;
NODST TST.L SCALECASE(A6) ;IS THERE A SCALE ROUTINE?
BEQ.S NOSCALE ;=>NO, DON'T ALLOCATE BUFFER
DOSCALE MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0
MOVE NUMER+H(A6),D0 ;GET DST WIDTH
SUB.l #1,D0 ;SUBTRACT 1 BIT @@@@ altered to use longs 03May88 BAL
LSL.l D4,D0 ;SCALE DSTBUF BY DSTSHIFT @@@@ altered to use longs 03May88 BAL
LSR.l #5,D0 ;AND DIV BY 32 FOR LONGS @@@@ altered to use longs 03May88 BAL
MOVE D0,SCALELONGS(A6)
SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT
CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP
CLRCHNK CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLRCHNK ;LOOP ENTIRE BUFFER
MOVE.L SP,SCALEBUF(A6) ;REMEMBER WHERE SCALEBUF IS
;_________________________________________________________________________________________
;
; CALC expansion buffer = [ (minRect.right-minRect.left) div 32 + 1 ] * pixelsize - 0
; CALC bufSize = [ (minRect.right-minRect.left) * pixelsize - 1 ] div 32 + 1 <C954> 08Nov87 BAL
;
NOSCALE MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE LEFT(A0),D1 ;GET DSTRECT LEFT
SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL COORDS
LSL.L D4,D1 ;CONVERT DST PIXELS TO BITS
AND #$FFE0,D1 ;TRUNC TO MULT OF 32
ASR.L D4,D1 ;CONVERT DST BITS TO PIXELS
ADD BOUNDS+LEFT(A5),D1 ;CONVERT BACK TO LOCAL
MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT
MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
SUB D1,D0 ;CALC WIDTH IN DOTS
MOVE D0,bufSize(A6) ;for arithmetic modes, prime bufSize with dot size
move d0,d1 ;save for expansion scanline buffer <C954>
ext.l d1 ;clear out high word <C954>
lsl.l d4,d1 ;convert to bits <C954>
subq.l #1,d1 ;force downward round <C954>
LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 <C954>
addq.l #1,d1 ;***make it one based for stretch!! <C954>
BTST #5,locMode+1(A6) ;arithmetic?
BNE.S @skipDotToLong ;if so, dont update bufSize
MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 <C954>
@skipDotToLong
LSR #5,D0 ;GET NUMBER OF LONGS IN SCANBUF
ADDQ #1,D0 ;MAKE IT ONE BASED
LSL D4,D0 ;MULTIPLY BY DST PIXEL DEPTH
;*** Leave it one based !!!?
SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK?
bpl.s @stkOK
_stNoStack ;=>NOT ENOUGH STACK, QUIT
@stkOK
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK.
;
CLR.L -(SP) ;TWO FOR SLOP
CLR.L -(SP) ;ONE FOR SLOP
CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR
DBRA D0,CLRMASK ;LOOP TILL DONE
MOVE.L SP,RGNBUFFER(A6) ;REMEMBER WHERE RGNBUFFER IS
;--------------------------------------------------------------------
;
; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
; GET SEEK ROUTINE INTO SEEKMASK(A6)
; GET EXPAND ROUTINE INTO EXRTN(A6) FOR SEEK ROUTINE
; Clobbers: A0-A3, D0-D6
;
move.l stNoStackPtr,goShow(a6) ;pass go home routine to getSeek <BAL 21Mar89>
clr.l runBuf(a6) ;don't use run clipping <1.5> BAL
move.l dstmaskbuf(a6),d7 ;save dstmaskbuf
tst.w maskshift(a6) ;deep mask?
beq.s @dontTrickGetSeek ;branch if no
clr.l dstmaskbuf(a6) ;make seek think there is no mask
@dontTrickGetSeek
MOVE.L RGNC(A6),-(SP) ;PUSH USER RGNHANDLE (never TrimRect'ed)
MOVE.L RGNB(A6),-(SP) ;PUSH VIS RGNHANDLE
MOVE.L RGNA(A6),-(SP) ;PUSH CLIP RGNHANDLE
MOVE.L #2,-(SP) ;PUSH HANDLE COUNT - 1
_GETSEEK ;GET EXPAND ROUTINE INTO EXRTN(A6)
;AND SEEK ROUTINE INTO SEEKMASK(A6)
move.l d7,dstmaskbuf(a6) ;restore
;--------------------------------------------------
;
; CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES
; GET INVERTFLAG INTO D7
;
SETMODE MOVE LOCMODE(A6),D0 ;GET THE MODE
BTST #5,D0 ;arithmetic mode?
BEQ.S @notArithMode
CMP #$40,D0 ;source modes are $20 … $27, $32
BGT DONE ;if bigger, undefined
BTST #3,D0 ;pattern?
BNE DONE
AND #$17,D0 ;consider only 8 mode variants
BCLR #4,D0 ;clear hilite bit
BEQ.S @notHilite
SUBQ #2,D0 ;hilite?
BNE DONE
ADDQ #8,D0 ;advance to hilite ($0C - 4)
@notHilite
cmp #16,dstPix+pixelSize(A6) ;dst 32 bits/pixel?
bge.s @useLoops16 ;yes, use alternate table
ADDQ #4,D0 ;advance past normal src modes
BRA.S @setupJump
@useLoops16
bne.s @useLoops32 ;yes, use alternate table
move.l stArith16TabPtr,A0 ;POINT TO 16 bit MODE TABLE
@getMode
BCLR #4,D0 ;clear hilite bit
add.l 0(A0,D0*4),A0 ;GET CASE JUMP ADDRESS
move.l a0,modeCase(a6) ;save for later
bra.s @gotMode
@useLoops32
move.l stArith32TabPtr,A0 ;POINT TO 32 bit MODE TABLE
bra.s @getMode
@notArithMode
MOVE.L INVERTFLAG(A6),D7 ;GET THE INVERT FLAG
BCLR #2,D0 ;CLEAR INVERT BIT
CMP #7,D0 ;IS MODE > 7 ?
BGT DONE ;YES, QUIT
@setupJump
LEA StretchModeTab,A0 ;POINT TO MODE TABLE (in trap table)
MOVE.L 0(A0,D0*4),MODECASE(A6) ;SAVE FOR LATER
@gotMode
;------------------------------------------------
;
; SET UP srcMergeCase
;
@noPromote
move.w srcshift(a6),d3 ;src depth
lea VMergeTable,a0 ;get base
add.l (a0,d3.w*4),a0 ;get routine offset from base
move.l a0,srcMergeCase(a6)
SourceMergeSetupDone
;------------------------------------------------
;
; SET UP maskMergeCase
;
clr.l CombineMaskCase(a6) ;assume no mask
clr.l maskMergeCase(a6) ;assume no mask
tst.l maskbits(a6) ;is there a mask?
beq nomask1 ;=>NO
move.w maskshift(a6),d0 ;mask depth, currently 0, 4, or 5
lea VMergeTable,a0 ;get base
add.l (a0,d0.w*4),a0 ;get displacement to routine
move.l a0,maskMergeCase(a6)
MergeSetupDone
;------------------------------------------------
;
; set up CombineMaskCase
;
tst maskshift(a6)
beq.s CombineMaskSetupDone ;one bpp mask
;
; Table is disorganized as follows:
;
; SRC DST MASK ENTRY
; 32 ind 32 0
; 32 16 32 1
; 32 32 32 2
;
; calc routine based on dst
;
;
; want indexed values to goto 0, 16 bit to 1, 32 bit to 2
;
move dstshift(a6),d0
subq #3,d0
spl d1
and d1,d0
lea CombineTable,a0 ;get base
add.l (a0,d0.w*4),a0 ;get displacement to routine
move.l a0,CombineMaskCase(a6)
CombineMaskSetupDone
;------------------------------------------------
;
; SET UP MASKALIGN AND MASKADDR IF THERE IS A MASK
;
MOVE MASKSHIFT(A6),D3 ;GET MASKSHIFT
LEA MASKPIX(A6),A2 ;POINT TO MASKPIX
MOVE.L MASKROW(A6),D2 ;GET MASK ROWBYTES
MOVE.L MASKRECT(A6),A0 ;POINT TO MASKRECT
MOVE LEFT(A0),D1 ;GET MASKRECT LEFT
SUB BOUNDS+LEFT(A2),D1 ;CONVERT TO MASK GLOBAL
EXT.L D1 ;MAKE LONG FOR BIG PIXELS
lsl.l d3,d1 ;convert pixels to bits
MOVEQ #$1F,D5 ;TREAT MOD 32 FOR MASKALIGN
AND.L D1,D5 ;MAKE A COPY
MOVE.L D5,MASKALIGN(A6) ;SAVE ALIGNMENT OF MASK
MOVE TOP(A0),D0 ;GET MASKRECT TOP
SUB BOUNDS+TOP(A2),D0 ;CONVERT TO MASK GLOBAL
MULS D2,D0 ;MULT BY MASK ROWBYTES BAL 02Dec88
ADD.L BASEADDR(A2),D0 ;GET START OF MASK BITMAP
SUB.L D5,D1 ;ADJUST MASKLEFT FOR MASKALIGN
ASR.L #3,D1 ;CONVERT BITS TO BYTES
ADD.L D1,D0 ;ADD BYTES TO MASKADDR
MOVE.L D0,MASKADDR(A6) ;SAVE AS MASKADDR
NOMASK1
;----------------------------------------------------------
;
; Jump into 32 bit addressing mode for blitting. @@@@ BAL 09Apr88
;
moveq #true32b,d0 ;switch to 32 bit addressing @@@@ BAL 09Apr88
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.b d0,MMUsave(a6) ;save previous state for later @@@@ BAL 09Apr88
;------------------------------------------------
;
; SET UP SRCROW, SRCSCANS, SRCSHIFT, AND SRCADDR
;
MOVE realSRCSHIFT(A6),D3 ;GET SRCSHIFT
LEA SRCPIX(A6),A2 ;POINT TO SRCPIX
MOVE.L SRCROW(A6),D2 ;GET SRC ROWBYTES
MOVE BOUNDS+BOTTOM(A2),D1 ;GET SRCBITS.BOUNDS.BOTTOM
SUB BOUNDS+TOP(A2),D1 ;MAKE IT GLOBAL
MOVE D1,SRCSCANS(A6) ;SAVE NUMBER OF SCANS TO DO
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE LEFT(A0),D1 ;GET SRCRECT LEFT
SUB BOUNDS+LEFT(A2),D1 ;CONVERT TO SRC GLOBAL
EXT.L D1 ;MAKE LONG FOR BIG PIXELS
LSL.L D3,D1 ;CONVERT SRC PIXELS TO BITS
MOVEQ #$1F,D5 ;TREAT MOD 32 FOR SRCSHIFT
AND.L D1,D5 ;MAKE A COPY
MOVE.L D5,SRCALIGN(A6) ;SAVE ALIGNMENT OF SOURCE
MOVE TOP(A0),D0 ;GET SRCRECT TOP
SUB BOUNDS+TOP(A2),D0 ;CONVERT TO SRC GLOBAL
MULS D2,D0 ;MULT BY SRC ROWBYTES BAL 02Dec88
ADD.L BASEADDR(A2),D0 ;GET START OF SRC BITMAP
SUB.L D5,D1 ;ADJUST SRCLEFT FOR SRCSHIFT
ASR.L #3,D1 ;CONVERT BITS TO BYTES
ADD.L D1,D0 ;ADD BYTES TO SRCADDR
MOVE.L D0,SRCADDR(A6) ;SAVE AS SRCADDR
@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
;
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.s @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
@CB1to8Clip jmpROM ciCB1to8Clip ;3A680
@CB8to8Clip jmpROM ciCB8to8Clip ;3A8E0
@CB8to1Clip jmpROM ciCB8to1Clip ;3AC6E
@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.s @CB8to1Clip ;if not, skip
@goSlow
;-----------------------------------------------------
;
; 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 ;<131>
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 ; <124> Old code for now
move maskDenom+v(a6),d2 ; <124>
endif ; <124>
if TheFuture then ; <124> New code for later
move maskNumer+v(a6),d2 ;<123>
endif ; <124>
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 srcpix+pmTable(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)
SrcMergeCaseReturn
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
MOVE.L colorTable(A6),A5 ;set up for arithmetic modes
CMP #$24,locMode(A6) ;transparent?
BNE.S @skipArith ;if not, regs are fine
BFEXTU transColor(A6){0:D7},D0
MOVE.L D0,A5
@skipArith
NXTMSK1 MOVE VERT(A6),D0 ;GET CURRENT VERT COORD
CMP MINRECT+TOP(A6),D0 ;IS VERT < MINV ?
BLT.S NODRAW ;YES, DON'T DRAW
;
; if mask is >1 bit/pixel, trick seek into ignoring mask by zeroing dstmaskbuf
;
move.l dstmaskbuf(a6),a4 ;save dstmaskbuf <KON 9JAN90>
tst maskshift(a6)
beq.s @NoTrickorTreat
clr.l dstmaskbuf(a6) ;make seek think there is no mask
@NoTrickorTreat
JSR ([SEEKMASK,A6]) ;MAKE MASK BUFFER CURRENT
move.l a4,dstmaskbuf(a6) ; <KON 9JAN90>
MOVE.L SCALEBUF(A6),A3 ;INIT SRCPTR
MOVE.L DSTADDR(A6),A4 ;INIT DSTPTR FOR ROW
MOVE.L RGNBUFFER(A6),A2 ;INIT MASKPTR FOR ROW
MOVE BUFSIZE(A6),D2 ;INIT COUNT OF LONGS
MOVE.L MODECASE(A6),A0 ;GET MODE CASE JUMP
BTST #5,locMode+1(A6) ;an arithmetic mode?
BEQ.S @skipArith
MOVE.L transColor(A6),D4 ;set up transparent color in case different from bg
CMP #$24,locMode(A6) ;transparent?
BEQ.S @skipInvTbl ;if so, D5 contains the pixels per long value
MOVE invSize(A6),D5 ;set up resolution of inverse table for arith. modes
@skipInvTbl
MOVEQ #0,D3 ;initialize destination pixel offset
MOVE.L dstAlign(A6),D6 ;reset alignment since it is bumped by arith. modes
SUB.L D7,D6 ;bump source pixel offset back by 1
@skipArith
CMP.L DSTPIX+BASEADDR(A6),A4 ;IS IT BEFORE THE PIXMAP?
BLO.S DSTNEG ;=>YES, DON'T PUT TO DST
DOBLT jsr (A0) ;TAKE MODE JUMP
NEXTDST MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES
ADD.L D0,DSTADDR(A6) ;BUMP DST TO NEXT ROW
NODRAW ADD #1,VERT(A6) ;BUMP TO NEXT VERT
MOVE VERT(A6),D0 ;GET VERT
CMP MINRECT+BOTTOM(A6),D0 ;ARE WE AT THE LAST SCAN LINE ?
BEQ.S DONE ;YES, QUIT
MOVE maskdenom+V(A6),D0 ;update mask error
SUB D0,maskERROR(A6)
MOVE DENOM+V(A6),D0
SUB D0,VERROR(A6) ;VERROR := VERROR - DENOM.V
BLT NEXTSRC ;IF VERROR < 0 THEN GET NEXT SRC <BAL 19Mar89>
tst.b useDither(a6) ; are we dithering? <BAL 19Mar89>
bne.s dstOK ; yes dither this scan again with current error <BAL 19Mar89>
BRA NXTMSK1 ;ELSE continue to draw from this src <BAL 19Mar89>
;-----------------------------------------------------------------
;
; HANDLE CASE WHERE DST IS NEGATIVE
;
DSTNEG MOVE.L DSTPIX+BASEADDR(A6),D1 ;GET ELUSIVE BASE ADDRESS
BTST #5,locMode+1(A6) ;AN ARITHMETIC MODE?
BEQ.S @NoRith ;=>NOPE, DO NORMAL
; IF ARITHMETIC MODE, BUMP ONE PIXEL AT A TIME UNTIL DST ISN'T NEGATIVE
@LOOP LEA 0(A4,D3),A1 ;GET CURRENT ADDRESS
CMP.L A1,D1 ;ARE WE STILL NEGATIVE?
BLS.S DOBLT ;=>NO, BLIT REST OF SCANLINE
SUBQ #1,D2 ;SKIP A DOT
BMI.S NEXTDST ;=>DONE WITH SCANLINE
ADD.L D7,D6 ;BUMP SRC POINTER ONE DOT
ADD.L D7,D3 ;BUMP DST POINTER ONE DOT
BRA.S @LOOP ;=>YES, KEEP SKIPPING
; IF NORMAL MODE, BUMP ONE LONG AT A TIME UNTIL DST ISN'T NEGATIVE
@NoRith LEA 4(A4),A1 ;GET NEXT LONG OF DST
CMP.L A1,D1 ;ARE WE STILL NEGATIVE
BLS.S DOBLT ;=>NO, BLIT REST OF SCANLINE
SUBQ #1,D2 ;SKIP NEXT LONG
BMI.S NEXTDST ;=>DONE WITH SCANLINE
ADDQ.L #4,A2 ;BUMP MASKPTR
ADDQ.L #4,A3 ;BUMP SRCPTR
ADDQ.L #4,A4 ;BUMP DSTPTR
BRA.S @NoRith ;=>TRY, TRY AGAIN
;-----------------------------------------------------------------
;
; ENTIRE STRETCHBITS COMPLETE. RESTORE REGS AND STACK AND GO HOME.
;
DoneStretch
DONE clr.w QDErr ;signal no error
doneErr move.b MMUsave(a6),d0 ;get previous MMU state in d0
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
SHOW MOVE.L SAVEA5(A6),A5 ;RESTORE A5
TST.B CRSRFLAG(A6) ;DID WE SHIELD THE CURSOR?
BEQ.S GOHOME ;=>NO, JUST RETURN
_SHOWCURSOR ;RESTORE CURSOR
GOHOME BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped
MOVE.L SAVESTK(A6),SP ;STRIP VARIABLE SIZED BUFFER
move.l stackHandle(a6),d0 ;did we allocate a handle?
beq.s @noTemp ;no, forget it.
move.l d0,a0 ;pass handle in a0
_DisposeTempBuffer ;dispose it.
move.l saveStkLowPt(a6),stkLowPt ;restart the sniffer <121> <09JUN92 SAH>
move.l oldHiHeapMark(a6),HiHeapMark ;restore extent of stack
@noTemp MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'STRETCHB'
ALIGN Alignment
stNoStack
tst.l StackFree(a6) ;did we run out of stack?
bpl.s SHOW ;no, just go home
movem.l d0-d3/a0-a2,-(sp) ;save state
neg.l d0 ;<BAL and KON 14Feb90>
move.l d0,stackFree(a6) ;<BAL and KON 14Feb90>
tst.l stackHandle(a6) ;have we been here before?
bne.s @noMem ;yes, forget it.
move.l HiHeapMark,oldHiHeapMark(a6) ;save extent of stack <09JUN92 SAH>
moveq #4,d0 ; <KON 14Feb90>
swap d0 ;try for 256K <BAL 14Feb90>
_NewTempBuffer ;returns a0=handle, d0=size
move.l d0,d2 ;copy the actual size
beq.s @noMem ;if zero, we didn't get it.
@gotit move.l a0,stackHandle(a6) ;remember to dispose it later
sub.l #qdStackXtra,d2 ;leave room for interrupts
asr.l #2,d2 ;make cnt of longs
add.l d2,stackFree(a6) ;new free cnt
bmi.s @noMem ;didn't get enough
clr.l stkLowPt ;disable stack sniffer
move.l a7,a2 ;remember where save regs are
move.l (a0),a0 ;get ptr
exg a0,d0 ;get ptr in d0, size in a0
_rTranslate24To32 ;strip it
move.l d0,HiHeapMark ;set up stack limit for _stackSpace
add.l d0,a0 ;point to end of block
move.l 7*4(a7),-(a0) ;copy over return address
move.l a0,a7 ;move the stack there
movem.l (a2),d0-d3/a0-a2 ;restore state
rts
@noMem move.w #nsStackerr,QDErr
bra.s SHOW
;******************************************************************************************
;--------------------------------------------
;
; Source scanline merge routines.
; There are 3 routines: OneDeep, NDeep, and Average16and32
; These routines copy from srcaddr to srcbuf and do vertical
; merging of source if necessary.
;
; When promoting source (ie dither mode) to 32 bit/pixel, Average16and32
; is called.
;
; EXPECTS: D0: D1: D2: D3:
; D4: D5:!SRCALIGN D6:!DSTALIGN D7:!INVERTFLAG
; A0: A1: A2: A3:
; A4: A5: A6: A7:
;--------------------------------------------
VMergeTable
dc.l oneDeep-VMergeTable ;src 1-bit/pixel
dc.l ndeep-VMergeTable ;src 2-bit/pixel
dc.l ndeep-VMergeTable ;src 4-bit/pixel
dc.l ndeep-VMergeTable ;src 8-bit/pixel
dc.l Average16and32-VMergeTable ;src 16-bit/pixel
dc.l Average16and32-VMergeTable ;src 32-bit/pixel
;--------------------------------------------
;
; Loop to combine d7 pixels of source and dest using mask
;
; ENTRY:
; D0: scratch A0: scratch
; D1: scratch A1: mask ptr
; D2: scratch A2: destination
; D3: scratch A3: src and dst ptr
; D4: scratch A4: src pmtable A5: rowbytes
; D5: srcAlign A5: rowbytes
; D6: realDepth (pixel size)
; D7: byte Count (zero based)
;
; There are 12 different cases: all combinations of source and mask
; being either 16- or 32-bits/pixel and dest being any depth. A mask
; of $ff means take source. The mask value ranges from 0-$7f,$81-$100.
CombineTable
;SRC DST MASK ENTRY
dc.l Combine32in32-CombineTable ;32 ind 32 0
dc.l Combine321632-CombineTable ;32 16 32 1
dc.l Combine323232-CombineTable ;32 32 32 2
;*******************************************************************
;
; CombineMaskCase
;
; Loop to combine d7 pixels of source and dest using mask
;
;ENTRY:
; D0: (dst) A0: address of routine called
; D1: (src) A1: mask ptr
; D2: (dst component) A2: destination
; D3: (mask) A3: src and dst ptr
; D4: (build pixel) A4: src pmtable A5: rowbytes
; D5: srcAlign A5:
; D6: realDepth (pixel size)
; D7: byte Count (zero based)
;
; There are 12 different cases: all combinations of source and mask
; being either 16- or 32-bits/pixel and dest being any depth. A mask
; of $ff means take source. The mask value ranges from 0-$7f,$81-$100.
;
;EXIT:
;
;
;*******************************************************************
;
; handle merging with indexed destinations, assume source and mask are 32 bpp
;
; Promote destination pixel to 32-bits/pixel, combine with source on a
; component by component basis according to value stored in mask
;
Combine32in32
bfextu (a2){d5:d6},d0 ;get a pixel of destination
add d6,d5 ;bump to next pixel
moveq #0,d4
move.w d4,d1 ;clear regs
move.w d4,d2
move.w d4,d3
move.b 1(a3),d2 ;get red of source
move.b ctTable+rgb+red(a4,d0.w*8),d1 ;get destination red into virgin reg
sub.w d2,d1 ;red dst - red source
move.b 1(a1),d3 ;get red mask
bpl.s @1
addq #1,d3 ;make mask go from 0 to 256
@1
muls.w d3,d1
lsl.w #8,d2 ;src*256
add.w d2,d1 ;(dst-src)*mask+(src*256)
move.w d1,d4 ;new red component (0000RRXX)
;
; now do green
;
move.w #0,d1 ;clear regs
move.w d1,d2
move.w d1,d3
move.b 2(a3),d2 ;get green of source
move.b ctTable+rgb+green(a4,d0.w*8),d1 ;get destination green into virgin reg
sub.w d2,d1 ;green dst - green src
move.b 2(a1),d3 ;get green mask
bpl.s @2
addq #1,d3 ;make mask go from 0 to 256
@2
muls.w d3,d1 ;(dst-src)*mask
lsl.w #8,d2 ;src*256
add.w d2,d1 ;(dst-src)*mask+(src*256)
lsr.w #8,d1
move.b d1,d4 ;move in green component (0000RRGG)
;
; now do blue
;
move.w #0,d1 ;clear regs
move.w d1,d2
move.w d1,d3
move.b 3(a3),d2 ;get blue of source
move.b ctTable+rgb+blue(a4,d0.w*8),d1 ;get destination green into virgin reg
sub.w d2,d1 ;blue dst - blue src
move.b 3(a1),d3 ;get green mask
bpl.s @3
addq #1,d3 ;make mask go from 0 to 256
@3
muls.w d3,d1 ;(dst-src)*mask
lsl.w #8,d2 ;src*256
add.w d2,d1 ;(dst-src)*mask+(src*256)
lsr.w #8,d1
lsl.l #8,d4 ;result = 00RRGG00
move.b d1,d4 ;move in blue component (00RRGGBB)
MOVE.L d4,(A3)+ ;PUT A LONG TO SRCBUF
addq #4,a1 ;bump to next mask
DBRA D7,Combine32in32 ;LOOP FOR ALL LONGS
rts
;
; Handle when src and mask are 32 bpp, dst is 16 bpp
;
Combine321632
move.l maskBC,a0 ;get useful Konstantin
Combine321632Loop
move.l (a1)+,d5 ;get a pixel of mask
bne.s @maskNonZero
addq.l #4,a3 ;mask 0 -> all src so just skip
addq.l #2,a2 ;bump destination
dbra D7,Combine321632Loop ;LOOP FOR ALL LONGS
rts
@maskNonZero
move.w (a2)+,d4 ;get a pixel of destination
cmp.l d5,a0 ;mask $7FFF?
beq @Writeout555 ;all dst, so write out d4
@DoSlowCase
move.w d4,d0 ;copy destination pixel
move.l (a3),d6 ;get a pixel of source
moveq #0,d4
move.w d4,d1 ;clear regs
move.w d4,d3
move.w d4,d2
swap d6
move.b d6,d2 ;get red of source
swap d6
move.w d0,d4 ;red destination in 14 - 10
lsr.w #7,d4 ;move red to bits 7 - 3
and.w #$00f8,d4 ;strip bits 2 - 0
move.b d4,d3
lsr.b #5,d3 ;replicate top 3 bits
or.b d3,d4 ;merge top five bits with top 3 bits
sub.w d2,d4 ;red dst - red src
swap d5
move.b d5,d3 ;get red mask
bpl.s @1
addq #1,d3 ;make mask go from 0 to 256
@1
swap d5
muls.w d3,d4 ;d2=(dst-src)*mask
asr.l #8,d4 ;(dst-src)*mask/256
add.l d2,d4 ;(dst-src)*mask/256+(src)
swap d4 ;new red component (00RR0000)
;
; now do green
;
move.w d6,d1 ;get green of source
lsr.w #8,d1 ;get green in low byte
move.w d0,d2 ;green destination in 9 - 5
lsr.w #2,d2 ;green in bits 7 - 3
and.w #$00f8,d2 ;strip bits 2 - 0
move.b d2,d3
lsr.b #5,d3 ;replicate top 3 bits
or.b d3,d2 ;merge top five bits with top 3 bits
sub.w d1,d2 ;green dst - green src
move.w d5,d3 ;get green mask
lsr.w #8,d3
tst.b d3
bpl.s @2
addq #1,d3 ;make mask go from 0 to 256
@2
muls.w d3,d2 ;d2 = (dst-src)*mask
lsl.w #8,d1 ;src*256
add.w d1,d2 ;(dst-src)*mask+(src*256)
move.w d2,d4 ;move in green component (00RRGGxx)
;
; now do blue
;
move.w #0,d1 ;clear regs
move.w d1,d3
move.b d6,d1 ;get blue of source
move.b d0,d2 ;blue destination in 4 - 0
lsl.w #3,d2 ;green in bits 7 - 3
and.w #$00f8,d2 ;strip bits 2 - 0
move.b d2,d3
lsr.b #5,d3 ;replicate top 3 bits
or.b d3,d2 ;merge top five bits with top 3 bits
sub.w d1,d2 ;blue dst - blue src
move.b d5,d3 ;get green mask
bpl.s @3
addq #1,d3 ;make mask go from 0 to 256
@3
muls.w d3,d2 ;(dst-src)*mask
lsl.w #8,d1 ;src*256
add.w d1,d2 ;(src-dst)*mask+(dst*256)
lsr.w #8,d2
move.b d2,d4 ;move in blue component (00RRGGBB)
@writeoutPixel
move.l d4,(a3)+ ;PUT A LONG TO SRCBUF
dbra D7,Combine321632Loop ;LOOP FOR ALL LONGS
rts
@Writeout555
;
; d4 has pixel to write out in 555: convert to 888 and write it out
;
moveq #0,d0
move.w d4,d0 ;red in 14-10
and.w #$7c00,d0
swap d0 ;red in 31-24
lsr.l #7,d0 ;red in 23-16
move.w d4,d0 ;green in 9-5
and.w #$03e0,d0
lsl.w #6,d0 ;green in 15-8
move.b d4,d0 ;blue in 4-0
and.b #$1f,d0
lsl.b #3,d0 ;blue in 7-0, green in 15-8, red in 23-16
move.l d0,d4
bra.s @writeoutPixel
;
; Handle when src, mask, dst all 32 bpp
;
Combine323232
move.l maskBC,a0 ;get useful Konstantin
Combine323232Loop
move.l (a1)+,d5 ;get a pixel of mask
bne.s @maskNonZero ;no, go the hard way
addq.l #4,a3 ;yes, all src so just skip
addq.l #4,a2 ;bump dst
dbra D7,Combine323232Loop ;LOOP FOR ALL LONGS
rts
@maskNonZero
move.l (a2)+,d4 ;get a pixel of destination
cmp.l d5,a0 ;mask $00FFFFFF?
beq.s @WriteoutPixel ;all dst, so write out d4
@DoSlowCase
move.l d4,d0 ;copy destination pixel
move.l (a3),d6 ;get a pixel of source
moveq #0,d4
move.w d4,d1 ;clear regs
move.w d4,d2
move.w d4,d3
swap d6
move.b d6,d2 ;get red of source
swap d0
swap d6
move.b d0,d4 ;get a pixel of destination
swap d0
sub.w d2,d4 ;red dst - red src
swap d5
move.b d5,d3 ;get red mask
bpl.s @1
addq #1,d3 ;make mask go from 0 to 256
@1
swap d5
muls.w d3,d4
asr.l #8,d4 ;(dst-src)*mask/256
add.l d2,d4 ;(dst-src)*mask/256+(src)
swap d4 ;new red component (00RR0000)
;
; now do green
;
move.w d6,d1 ;get green of source
move.w d0,d2 ;get a pixel of destination
lsr.w #8,d1 ;get green in low byte
lsr.w #8,d2 ;get green in low byte
sub.w d1,d2 ;green dst - green src
move.w d5,d3 ;get green mask
lsr.w #8,d3
tst.b d3
bpl.s @2
addq #1,d3 ;make mask go from 0 to 256
@2
muls.w d3,d2 ;(dst-src)*mask
lsl.w #8,d1 ;src*256
add.w d1,d2 ;(dst-src)*mask+(src*256)
move.w d2,d4 ;move in green component (00RRGGxx)
;
; now do blue
;
move.w #0,d1 ;clear regs
move.w d1,d2
move.w d1,d3
move.b d6,d1 ;get blue of source
move.b d0,d2 ;get blue of destination
sub.w d1,d2 ;blue dst - blue src
move.b d5,d3 ;get green mask
bpl.s @3
addq #1,d3 ;make mask go from 0 to 256
@3
muls.w d3,d2 ;(dst-src)*mask
lsl.w #8,d1 ;src*256
add.w d1,d2 ;(src-dst)*mask+(dst*256)
lsr.w #8,d2
move.b d2,d4 ;move in blue component (00RRGGBB)
@writeoutPixel
move.l d4,(a3)+ ;PUT A LONG TO SRCBUF
dbra D7,Combine323232Loop ;LOOP FOR ALL LONGS
rts
;*********************************************************************
;
; Loop to expand and merge D7 scanlines of indexed pixels
;
;ENTRY:
; D0: scratch A0: scratch ptr
; D1: scratch A1: scratch ptr
; D2: scratch A2: destination
; D3: scratch A3: source
; D4: src longs A4: src pmtable
; D5: srcAlign A5: rowbytes
; D6: realDepth (pixel size)
; D7: Scanline Count (zero based)
;
;EXIT:
;
; a3: new srcaddr
;
;GLOBALS: AvgBufPtr(a6), AvgBufSize(a6)
;
;*********************************************************************
NDEEP
; LOOP FOR ALL LONGS IN SRC SCANLINE
move.l a3,a0 ;point to source
move.l a2,a1 ;point to destination
move d4,d1 ;get count of longs
@Align bfextu (a0){d5:0},d0 ;get an aligned long of source
add #4,a0 ;bump to next long
move.l d0,(a1)+ ;put a long to destination
dbra d1,@Align ;loop for all longs
; add.l a5,a3 ;bump source to next row
_pmVersion
subq #1,d7
bpl.s @1
rts
; do verticle merging
@1
move d6,d3 ;get pixel depth
move.w d4,a4 ;save count of longs
NdeepMerge
move.l d7,-(sp) ;save count of lines to do
move.l a3,a0 ;point to source
move.l a2,a1 ;point to destination
move a4,d6 ;get long count
moveq #0,d4 ;start at beginning of long
ndlong bfextu (a0){d5:0},d0 ;extract a long from source
move.l (a1),d1 ;get next long from destination
ndpxl bfextu d0{d4:d3},d2 ;get pixel from source
bfextu d1{d4:d3},d7 ;get pixel from destination
cmp.l d7,d2 ;which is greater?
ble.s nochng ;only change if source is greater
bfins d2,d1{d4:d3} ;replace pixel is destination
NOCHNG add d3,d4 ;bump to next pixel within long
and #$1f,d4 ;done with long?
bne.s ndpxl ;no, keep looping
add #4,a0 ;bump src offset
move.l d1,(a1)+ ;write to destination
dbra d6,ndlong ;repeat for all longs
; add.l a5,a3 ;add rowbytes to src pointer
move.l (sp)+,d7 ;retrieve line count
_pmVersion
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
jmpROM ciScale16to32 ;inherits return address
@CopyLoop
move.l (a0)+,(a2)+ ;copy source to destination
dbra D1,@CopyLoop ;loop for all longs
@SrcBufFull
; add.l a5,a3 ;bump source to next row
_pmVersion
rts
;------------------------------------------------------------------------
@Average
;
; average 16 or 32 bit source
;
useAverageBuf
moveq #0,d1 ;get a useful constant
; Init R-G-B accumulation buffer to zero
move.w ABufSize(a6),d0 ;get count of longs in buffer
move.l AvrgBuf(a6),a0 ;point at buffer
@1 move.l d1,(a0)+ ;clear it out
dbra d0,@1
;
; Are we averaging 16-bit or 32-bit data?
;
move.w d7,-(sp) ;save scanline count
cmp #16,d6 ;16-bit data?
beq NextAverageV16 ;YES: do 16-bit average loop
; Top of 32-bit scanline averaging loop
NextAverageV32
; loop for all longs in source scanline
move.l d5,d2 ;GET SHIFT FOR SRC ALIGNMENT
move.l a3,a0 ;point to source buffer
move.l AvrgBuf(A6),A1 ;point to accumulation buffer
move d4,d3 ;get count of source
;-------------------------------------------------------------------------
;
; If dithering or averaging an indexed src then first pre-Expand it
; to 32 bit/pixel RGB data.
;
cmp.w #32,d6 ;promoting src to RGB?
beq @NDLONG0 ;no, all ok
;
; if no color table, use grey scale
;
tst.l a4 ;color table?
beq.s @NoCTab
@Xpand BFEXTU (a0){D2:D6},D0 ;get a pixel of src
add d6,d2 ;bump to next pixel
move.l ctTable+rgb+red(a4,d0.w*8),d1 ;get RRrrGGgg
swap d1 ;get GGggRRrr
lsr.w #8,d1 ;get GGgg00RR
add.w d1,(a1)+ ;accumulate red value
swap d1 ;get 00RRGGgg
lsr.w #8,d1 ;get 00RR00GG
add.w d1,(a1)+ ;accumulate green value
move.b ctTable+rgb+blue(a4,d0.w*8),d1 ;get 00RR00BB
add.w d1,(a1)+ ;accumulate blue value
dbra d3,@Xpand ;LOOP FOR ALL LONGS
; add.l a5,a3 ;bump to next source row
_pmVersion
dbra d7, NextAverageV32 ;accumulate d7 scanlines
bra MakeAverage
@NoCTab BFEXTU (A0){D5:D6},D0 ;get a pixel of src
add d6,d5 ;bump to next pixel
;
; replicate pixel first to 8 bits and then to 24
;
move.w d0,d1
MOVEQ #8,D2 ;replicate to byte size
@NXTPXL SUB D6,D2 ;SAY WE'VE DONE A PIXEL
BLE.S @RepDone ;=>IT WAS THE LAST ONE
LSL.w D6,D0 ;replicate
OR.w D1,D0 ;INSTALL FG PIXEL
BRA.S @NXTPXL ;=>DO ENTIRE LONG
; d0 has xxxxxxBB
@RepDone
not.b d0 ;invert it since 00 = black in RGB and white in index
and.w #$00FF,d0
add.w d0,(a1)+ ;accumulate red value
add.w d0,(a1)+ ;accumulate green value
add.w d0,(a1)+ ;accumulate blue value
dbra d3,@NoCTab ;LOOP FOR ALL LONGS
; add.l a5,a3 ;bump to next source row
_pmVersion
dbra d7, NextAverageV32 ;accumulate d7 scanlines
bra.s MakeAverage
;------------------------------------------------------------------------
;
;
;
@NDLONG0
moveq #0,d1
moveq #0,d2 ;use for extending to word data
moveq #0,d5
@NDLONG move.l (a0)+,D0 ;EXTRACT A LONG FROM SRC
move.b d0,d1 ;pick up blue component as a word
lsr.l #8,d0 ;toss blue
move.b d0,d2 ;pick up green component as a word
lsr.l #8,d0 ;toss green
move.b d0,d5 ;pick up red component as a word
add.w d5,(a1)+ ;accumulate blue value
add.w d2,(a1)+ ;accumulate green value
add.w d1,(a1)+ ;accumulate red value
DBRA d3,@NDLONG ;=>REPEAT FOR ALL LONGS
; add.l a5,a3 ;bump to next source row
_pmVersion
dbra d7, NextAverageV32 ;accumulate d7 scanlines
MakeAverage
move.w (sp)+,d7 ;restore scanline count (0-based)
addq #1,d7 ;make it 1 based
; Now we must compute the average of the accumulated R-G-B's
move.l a2,a1 ;pointer to destination buffer
move.l AvrgBuf(A6),A0 ;point to accumulation buffer
move d4,d3 ;longs in source
cmp.w #2,d7 ;merged exactly 2 scanlines?
beq.s @useShift ;avoid division by using a shift
@hardWay
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up red accumulation
divu.w d7,d1 ;get red average
move.b d1,d0 ;put in low byte of pixel <KON MAY90>
lsl.l #8,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up green accumulation
divu.w d7,d1 ;get green average
move.b d1,d0 ;put in low byte of pixel
lsl.l #8,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up blue accumulation
divu.w d7,d1 ;get red average
move.b d1,d0 ;put in low byte of pixel
move.l d0,(a1)+ ;dump pixel into destination
dbra d3,@hardWay ;loop for all src longs
rts
@useShift
moveq #0,d0 ;zero alpha channel <KON MAY90>
move.w (a0)+,d1 ;pick up red accumulation
lsr.w #1,d1 ;get red average
move.b d1,d0 ;put in low byte of pixel <KON MAY90>
lsl.l #8,d0 ;make room for next component
move.w (a0)+,d1 ;pick up green accumulation
lsr.w #1,d1 ;get green average
move.b d1,d0 ;put in low byte of pixel
lsl.l #8,d0 ;make room for next component
move.w (a0)+,d1 ;pick up blue accumulation
lsr.w #1,d1 ;get red average
move.b d1,d0 ;put in low byte of pixel
move.l d0,(a1)+ ;dump pixel into srcBuf
dbra d3,@useShift ;loop for all src longs
rts
;-------------- Top of 16-bit average loop -----------------
; Top of 16-bit scanline averaging loop
; d7 and word at top of stack is number of scanlines to merge
;
NextAverageV16
;
; loop for all longs in source scanline
;
move.l a3,a0 ;get source address
move.l AvrgBuf(A6),A1 ;point to accumulation buffer
move d4,d5 ;get count of source
moveq #0,d1 ;use for extending to word data
moveq #0,d2 ;use for extending to word data
moveq #0,d3 ;use for extending to word data
;------------------------------------------------------------------------
@NDLONG move.l (A0)+,D0 ;EXTRACT A LONG FROM SRC (2 pixels)
move.b d0,d3 ;pick up blue component as a byte
and.b #$1f,d3
lsr.l #5,d0 ;toss blue
move.b d0,d2 ;pick up green component as a byte
and.b #$1f,d2
lsr.l #5,d0 ;toss green
move.b d0,d1 ;pick up red component as a word
and.b #$1f,d1
add.w d1,(a1)+ ;accumulate red value
add.w d2,(a1)+ ;accumulate green value
add.w d3,(a1)+ ;accumulate blue value
;
; Do second pixel in long
;
lsr.l #5+1,d0 ;move to second 16-bit pixel in long
move.b d0,d3 ;pick up blue component as a byte
and.b #$1f,d3
lsr.l #5,d0 ;toss blue
move.b d0,d2 ;pick up green component as a byte
and.b #$1f,d2
lsr.l #5,d0 ;toss green
move.b d0,d1 ;pick up red component as a word
and.b #$1f,d1
add.w d1,(a1)+ ;accumulate red value
add.w d2,(a1)+ ;accumulate green value
add.w d3,(a1)+ ;accumulate blue value
dbra d5,@NDLONG ;repeat for all longs
; add.l a5,a3 ;bump source to next row
_pmVersion
dbra d7,NextAverageV16 ;loop while scan lines left
move.w (a7)+,d7 ;retrieve # scanlines merged (0-based)
addq #1,d7 ;make it 1 based
; Now we must compute the average of the accumulated R-G-B's
move.l a2,a1 ;point to destination buffer
move.l AvrgBuf(A6),A0 ;point to accumulation buffer
move d4,d3 ;longs in source
;
; if it's a deep mask, we promote all 16-bit values to 32-bit
;
move.w maskshift(a6),d0
cmp.w #4,d0
bge Promote16Loop
cmp.w #2,d7 ;two scan lines merged?
beq.s @useShift ;avoid division by using a shift
@hardWay
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up red accumulation
divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear)
move.w d1,d0 ;put in low byte of pixel (only 6 bits count)
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up green accumulation
divu.w d7,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up blue accumulation
divu.w d7,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
;
; Now do second pixel in long
;
lsl.l #5+1,d0 ;bump to beginning of second pixel
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up red accumulation
divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear)
or.w d1,d0 ;put in low byte of pixel (only 5 bits count)
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up green accumulation
divu.w d7,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up blue accumulation
divu.w d7,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
swap d0 ;pixels mixed in AvrgBuf because of how constructed
move.l d0,(a1)+ ;dump pixel into srcBuf
dbra d3,@hardWay ;loop for all src longs
rts
@useShift
move.w (a0)+,d1 ;pick up red accumulation
lsr.b #1,d1 ;get red average
move.w d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up green accumulation
lsr.b #1,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up blue accumulation
lsr.b #1,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
;
; do second pixel (2/long in 16-bit mode)
;
lsl.l #5+1,d0
move.w (a0)+,d1 ;pick up red accumulation
lsr.b #1,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up green accumulation
lsr.b #1,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up blue accumulation
lsr.b #1,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
swap d0
move.l d0,(a1)+ ;dump pixel into srcBuf
dbra d3,@useShift ;loop for all src longs
rts
Promote16Loop
;
; Average 16 bit values and put result back in AvrgBuf, then call
; Scale16to32 to promote to 32 bits
;
move.l a0,a1 ;copy AvrgBuf ptr
cmp.w #2,d7 ;two scan lines merged?
beq.s @useShift ;avoid division by using a shift
@hardWay
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up red accumulation
divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear)
move.w d1,d0 ;put in low byte of pixel (only 6 bits count)
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up green accumulation
divu.w d7,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up blue accumulation
divu.w d7,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
;
; Now do second pixel in long
;
lsl.l #5+1,d0 ;bump to beginning of second pixel
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up red accumulation
divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear)
or.w d1,d0 ;put in low byte of pixel (only 5 bits count)
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up green accumulation
divu.w d7,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
moveq #0,d1 ;use for extending to word data
move.w (a0)+,d1 ;pick up blue accumulation
divu.w d7,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
swap d0 ;pixels mixed in AvrgBuf because of how constructed
move.l d0,(a1)+ ;dump pixel into srcBuf
dbra d3,@hardWay ;loop for all src longs
bra.s @DoPromote
@useShift
move.w (a0)+,d1 ;pick up red accumulation
lsr.b #1,d1 ;get red average
move.w d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up green accumulation
lsr.b #1,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up blue accumulation
lsr.b #1,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
;
; do second pixel (2/long in 16-bit mode)
;
lsl.l #5+1,d0
move.w (a0)+,d1 ;pick up red accumulation
lsr.b #1,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up green accumulation
lsr.b #1,d1 ;get green average
or.b d1,d0 ;put in low byte of pixel
lsl.l #5,d0 ;make room for next component
move.w (a0)+,d1 ;pick up blue accumulation
lsr.b #1,d1 ;get red average
or.b d1,d0 ;put in low byte of pixel
swap d0
move.l d0,(a1)+ ;dump pixel into srcBuf
dbra d3,@useShift ;loop for all src longs
@DoPromote
;
; Call Scale16to32 to promote pixels to 32 bpp
;
move.l AvrgBuf(A6),A0 ;pointer to source
move.l a2,a1 ;pointer to destination
lsl.l #3,d4 ;calc size of dst:
;longs to bytes and 16 bit to 32 bit = *8 <7JULY90 KON>
add.l d4,a2 ;calc end of dst buffer
jmpROM ciScale16to32 ;inherits return address.
;
;----------------Bottom of 16-bit average loop ----------------
;
;*********************************************************************
ALIGN Alignment
;*********************************************************************
;
; Loop to expand and merge D7 1-bit/pixel scanlines.
;
;ENTRY:
; D0: scratch A0: scratch ptr
; D1: scratch A1: scratch ptr
; D2: scratch A2: destination
; D3: scratch A3: source
; D4: src longs A4: src pmtable A5: rowbytes
; D5: srcAlign A5: rowbytes
; D6: realDepth (pixel size)
; D7: Scanline Count (zero based)
;
;EXIT:
;
; a3: new srcaddr
;
;GLOBALS: AvgBufPtr(a6), AvgBufSize(a6)
;
;*********************************************************************
ONEDEEP
; LOOP FOR ALL LONGS IN SRC SCANLINE
move.l a3,a0 ;point to source
move.l a2,a1 ;point to destination
move d4,d1 ;get count of longs
@Align bfextu (a0){d5:0},d0 ;get an aligned long of source
add #4,a0 ;bump to next long
move.l d0,(a1)+ ;put a long to destination
dbra d1,@Align ;loop for all longs
; add.l a5,a3 ;bump source to next row
_pmVersion
dbra d7,@OneMerge ; <KON 1NOV90>
rts
@OneMerge
move.l a3,a0 ;point to source
move.l a2,a1 ;point to destination
move d4,d1 ;get count of longs
@NXTLNG bfextu (a0){d5:0},d0 ;get an aligned long of source
add #4,a0 ;bump to next long
or.l d0,(a1)+ ;put a long to destination
dbra d1,@NXTLNG ;loop for all longs <10July90 KON>
; add.l a5,a3 ;bump source to next row
_pmVersion
dbra d7,@OneMerge
rts
;******************************************************************************************
;=========================================================================================
;=========================================================================================
;
; Patch to stMask0 and stMask1 to colorize only when needed.
;
;=========================================================================================
;=========================================================================================
ALIGN Alignment
;-------------------------------------------------------
;
; 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?
BEQ.S @1 ;no, use normal loops
LEA stAlphaMask0,A0 ;get address of alpha copy loop
BRA.S @RememberAndDoIt ;go remember and do it
@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
;
;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
rts
;
; 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
rts ;GO FOR NEXT ROW
stAlphaMask0 ;(ENTIRE LOOP)
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
AND.L (A2)+,D0
AND.L D5,D0
EOR.L D1,D0
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
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
rts ;GO FOR NEXT ROW
;
; The eight bit loops are moved to RAM by code at the end of this file. <KON 09OCT90>
;
ALIGN Alignment
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? <85>
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
;--------------------------------------------------------------------------
;
;
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; BRA NEXTDST ;LOOP FOR NEXT ROW
;--------------------------------------------------------------------------
;
;
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; 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
rts
; BRA NEXTDST ;LOOP FOR NEXT ROW
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
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to BitsToPix. Add support changing baseAddrs.
; Also check if from paint vector. If so, abort paint vector if VCount=0
;
;=========================================================================================
;=========================================================================================
BitsToPix PROC EXPORT
FromPaintVector equ $33EC6
AbortPaintVector equ $343FC
ciROMNotScreen equ $30406
ciROMnot32Bit equ $303CE
ciROMbase32 equ $30468
ciROMbase24 equ $30462
;-------------------------------------------------------------
;
; PROCEDURE BitsToPix (XM: XMap; VAR PM: PixMap);
;
; See description in ColorAsm.a. This patch allows GDevice base addresses to change
; when the depth changes.
;
cmpRA FromPaintVector,(sp)
bne.s NormalBitsToPix
;
; From PaintVector: We still have paint vector's stack frame
;
ParamSize Equ 18
Vector Equ ParamSize+8-4
VCount Equ Vector-2
EoFill Equ VCount-2
VectRect Equ EoFill-4
Mode Equ VectRect-2
Pat Equ Mode-4
tst.w VCount(a6) ;number of edges 0?
bne.s NormalBitsToPix ;no, carry on.
;
; Here we caught the case we are looking for.
; Jump to the end of Bits to Pix which will clean up the stack for us.
;
jmpROM AbortPaintVector
NormalBitsToPix
MOVEQ #0,D2 ;ASSUME NOT SCREEN
MOVE ROWBYTES(A1),D0 ;IS SRC A PIXMAP?
BPL.S DOBITMAP ;=>NO, IT'S A BITMAP
BTST #isCPort,D0 ;IS IT A COLOR GRAFPORT?
BEQ.S NOTPORT ;=>NO, NOT A PORT
; IT'S A PIXMAP, SEE IF IT'S THE SCREEN
MOVE.L BASEADDR(A1),A1 ;GET HANDLE TO PORT'S PIXMAP
MOVE.L (A1),A1 ;GET POINTER TO PORT'S PIXMAP
NOTPORT MOVE.L BOUNDS+TOPLEFT(A1),D1 ;RETURN BOUNDS.TOPLEFT IN D1
MOVE.L ScrnBase,D0 ;GET MainScreen.BASEADDR
CMP.L BASEADDR(A1),D0 ;IS IT TO THE SCREEN?
BNE.S COPYPMAP ;=>NO, GO COPY IT
BRA.S ISSCREEN ;=>ELSE IT IS THE SCREEN
; IT'S A BITMAP. SEE IF IT'S THE SCREEN
DOBITMAP MOVE.L BOUNDS+TOPLEFT(A1),D1 ;RETURN BOUNDS.TOPLEFT IN D1
MOVE.L ScrnBase,D0 ;GET MainScreen.BASEADDR
CMP.L BASEADDR(A1),D0 ;IS BITMAP BASEADDR SAME ?
beq.s ISSCREEN ;
jmpROM ciROMNotScreen
ISSCREEN MOVEQ #1,D2 ;SET SCREEN FLAG FOR CALLER
MOVE.L THEGDEVICE,A0 ;GET HANDLE TO THE GDEVICE
MOVE.L (A0),A0 ;GET POINTER TO THE GDEVICE
btst #ext32Device,gdFlags(a0) ;does it need 32-bit addressing?
beq.s @not32Bit
moveq #-1,d2 ;is screen and needs 32-bit addressing
@not32Bit ;
jmpROM ciROMnot32Bit
SpecialBase
move.l (a1)+,a0 ;get baseAddr
btst #1,d0 ;is this a handle?
beq.s @notHand ;no, don't deref
move.l (a0),a0 ;yes, dereference it
@notHand btst #2,d0 ;32-bit clean address?
exg a0,d0 ;get address in d0, don't change cc's
beq.s base24 ;no flag -> 24-bit addressing
moveq #-1,d2 ;
clr.w d2 ;set needs 32-bit addressing flag, not screen
jmpROM ciROMbase32 ;flag set-> 32-bit addressing
; COPY THE SRC TO THE DST
COPYPMAP
move.w pmVersion(a1),d0 ;get baseAddr flags
bne.s SpecialBase ;if flags set go decide
MOVE.L (A1)+,d0 ;COPY BASEADDR
base24 jmpROM ciROMbase24
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to InitGDevice. Add support for GDevices with baseAddrs that change across
; depths (Trident card) in a MultiFinder friendly way.
;
;=========================================================================================
;=========================================================================================
InitGDevice PROC EXPORT
WITH VDPageInfo ;<1.1>
ciROMGetDevPixMap EQU $27A30
;-------------------------------------------------------------
;
; PROCEDURE InitGDevice (refNum: INTEGER; mode: LONGINT; GDH: GDHandle);
;
; Initialize the specified device to the specified mode. The GDevice
; data is placed into the provided handle.
;
; If mode = -1 then the driver is not called. It is assumed that the pixmap
; has been set up before InitGDevice is called.
;
; CAUTION: this routine is used during ROM boot; various Macintosh functions
; may not yet be available! <dvb - found out the hard way>
;
IGDVars RECORD {A6Link},DECREMENT
result DS.B 0 ; no result
REFNUM DS.B 2
MODE DS.B 4 ; LONG, mode for video card
GDH DS.B 4 ; LONG, handle to devPort
return DS.B 4 ; the return address
A6Link DS.B 4 ; our link
IOPBlk DS.B IOVQElSize ; [64] parameter blk for I/O calls
VidParms DS.B 12 ; [12] size of mode params
GDHState DS.B 2 ; [word] lock state of GDH
GDPState DS.B 2 ; [word] lock state of GDP
SaveDevice DS.B 4 ; [long] saved device handle
oldBaseAddr DS.B 4 ; old base address, for later comparison
oldPort DS.B 4 ; thePort, before we got here
oldColor DS.B 8 ; a colorSpec used to reinstantiate fg/bk
VARSIZE DS.B 0 ; size of locals
ENDR
WITH IGDVars
LINK A6,#VARSIZE ; allocate stack frame
MOVEM.L D3/A2-A4,-(SP) ; save off work registers
MOVE.L GDH(A6),A0 ; get the gDevice handle
_HGetState ; get the current lock state
MOVE D0,GDHState(A6) ; save the state
_HLOCK ; and lock down the gDevice
MOVE.L (A0),A2 ; get pointer to gDevice record
MOVE.L GDPMap(A2),A0 ; get handle to pixMap
MOVE.L (A0),A1 ; A1->pixmap
MOVE.L baseAddr(A1),oldBaseAddr(A6) ; save the base address, for later portfixing
_HGetState ; get the current lock state of the pixmap
MOVE D0,GDPState(A6) ; save the state
_HLOCK ; lock it down
MOVE.L (A0),A3 ; keep pointer in A3
MOVE.L theGDevice,SaveDevice(A6) ; save theGDevice
TST.B QDExist ; qd around?
BNE.S @noShield ; no, don't shield cursor
BTST #screenDevice,gdFlags(A2) ; is it screen (check hi byte with #>8)
BEQ.S @noShield
PEA gdRect(A2)
CLR.L -(SP) ; in global coörds
_ShieldCursor
@noShield
; initialize the GDevice's mode and refnum
MOVE REFNUM(A6),GDRefNum(A2) ; set up RefNum
MOVE.L MODE(A6),D0 ; get the mode
CMP.L MinusOne,D0 ; is the mode -1?
BEQ ModeOK ; if so, then don't call the driver
; set up the driver parameter block in case we need to use it
LEA IOPBlk(A6),A0 ; point to parameter block
CLR.L ioCompletion(A0) ; no completion routine
CLR.W ioVRefNum(A0) ; no volRefNum
MOVE RefNum(A6),ioRefNum(A0) ; set device's refnum
LEA VidParms(A6),A1 ; point to params for GetMode
MOVE.L A1,csParam(A0) ; point to param list
CMP.L GDMode(A2),D0 ; has the mode changed?
BEQ GrayOrColor ; => no, so don't set depth
MOVE.L D0,GDMode(A2) ; set up mode
; setup the gDevice fields for the new screen depth
CLR GDCCDepth(A2) ; invalidate cursor depth <C837>
MOVEM.L A0/A1,-(SP) ; save these regs
MOVE REFNUM(A6),-(SP) ; push refnum
MOVE.L MODE(A6),-(SP) ; push mode
MOVE.L GDPMap(A2),-(SP) ; pixMap handle
PEA GDType(A2) ; point to device type
jsrROM ciROMGetDevPixMap ; read in pixMap from device
MOVEM.L (SP)+,A0/A1 ; restore them
; first, set the mode (A0 points to IOPB, A1 to control parameter block)
MOVE #2,csCode(A0) ; csc_GetMode
MOVE.L mode(A6),D0 ; get the mode
MOVE D0,csMode(A1) ; set desired mode
CLR csPage(A1) ; set page 1
CLR.L csData(A1) ; no additional data
_Control ,IMMED ; SetMode(Mode,Page,Data);
; then gray the screen
MOVE #5,csCode(A0) ; csc_GrayPage
_Control ,IMMED ; paint current page gray
; set the device to color or monochrome, according to GDFlags
GrayOrColor
MOVE GDFlags(A2),D0 ; get flags word
NOT D0 ; flip all bits
AND #1,D0 ; clear all but low bit
MOVE.B D0,csMode(A1) ; csMode = color/gray scale
MOVE #6,csCode(A0) ; csc_SetGray
_Control ,IMMED ; set color or monochrome
; if the device has a color table, set the device's color table
CMP #ClutType,GDType(A2) ; is there a lookup table?
BNE.S NoTbl ; =>no, don't set one
MOVE.L pmTable(A3),A0 ; get handle to color table
_HLock ; lock down the color table
;+++ LEA VidParms(A6),A1 ; point to params for SetEntries
MOVE.L (A0),A0 ; get ctabPtr <DAF>
CLR.W csStart(A1) ; start at zero, use sequence mode <DAF>
MOVE.W ctSize(A0),csCount(A1) ; for the length of the table <DAF>
LEA ctTable(A0),A0 ; get pointer to colorspecs <DAF>
MOVE.L A0,csTable(A1) ; color table pointer is first param <DAF>
LEA IOPBlk(A6),A0 ; point to parameter block
MOVE.W #3,csCode(A0) ; csc_SetEntries
MOVE.L A1,csParam(A0) ; move addr of parms into block
_Control ,IMMED ; SetEntries(ColorTable);
MOVE.L pmTable(A3),A0 ; get handle to color table
_HUnlock ; unlock the color table
NoTbl
; if CLUT or fixed color table, build inverse table
CMP #DirectType,GDType(A2) ; should there be an inverse table?
BEQ.S ModeOK ; =>no inverse table
MOVE.L pmTable(A3),-(SP) ; push color table handle
MOVE.L GDITable(A2),-(SP) ; push inverse table handle
MOVEQ #4,D0 ; make 4-4-4 inverse tables
MOVE D0,GDResPref(A2) ; save in GDevice
MOVE D0,-(SP) ; and push res
_MakeITable ; and generate table
; If this device has not been initialized from the system file, then copy the
; bounds from the pixMap to the GDRect. Otherwise copy the GDRect to the Bounds.
ModeOK
LEA BOUNDS(A3),A0 ; point to pixmap.bounds <C837>
LEA GDRECT(A2),A1 ; point to device's global rect
MOVE GDFlags(A2),D0 ; get the flags word
BTST #RAMInit,D0 ; initialized from RAM?
BEQ.S BndsOK ; => no, copy pixMap.bounds to GDRect
EXG A0,A1 ; else copy GDRect to pixMap.bounds
BndsOK MOVE.L (A0)+,(A1)+ ; copy topLeft
MOVE.L (A0)+,(A1)+ ; copy botRight
; <dvb 3Jan89>
; if we're about the main device, then fix all those
; potentially errant ports.
;
TST.B QDExist ; (Unless QuickDraw don't exist)
BNE @noQD
MOVE.L portList,D1 ; or if portlist = 0 or -1
BEQ @noQD
ADDQ.L #1,D1
BEQ @noQD
BTST #mainScreen,D0 ; is it the main scrn? (flags already in D0)
BEQ @notMain
PEA oldPort(A6) ; Save the current port
_GetPort
MOVE.L mainDevice,theGDevice ; and set to the screen
MOVE.L PortList,A4 ; A4 = handle to list of ALL ports
MOVE.L (A4),A4 ; A4->list of all ports
MOVE (A4),D3 ; D3 = number of ports that exist
BRA.S @portWalkEnd
@portWalkLoop
MOVE.L PortList,A4
MOVE.L (A4),A4
MOVE.L 2(A4,D3.W*4),A4 ; A4 = this port
MOVE.L A4,-(SP) ; Set to each port in the port list
_SetPort
MOVE.L oldBaseAddr(A6),D1 ; D1 = the scrnbase of ports to change
BTST #7,portVersion(A4) ; high bit set?
BEQ.S @oldPort
MOVE.L portPixMap(A4),A4 ; A4 = handle to the port's pixmap
MOVE.L (A4),A4 ; A4->port's pixmap
CMP.L baseAddr(A4),D1 ; same as the screen's?
BNE.S @portWalkEnd ; no, skip this port
MOVE.L baseAddr(A3),baseAddr(A4) ; replace a bunch of fields
MOVE rowBytes(A3),rowBytes(A4)
MOVE.L pixelType(A3),pixelType(A4) ; (gets pixelSize, too)
MOVE.L cmpCount(A3),cmpCount(A4) ; (gets cmpSize, too)
MOVE.L planeBytes(A3),planeBytes(A4)
PEA oldColor(A6) ; placeholder for reinstantiating colors
MOVE.L (SP),-(SP)
MOVE.L (SP),-(SP)
MOVE.L (SP),-(SP)
_SaveFore ; Save and restore the foreground color
_RestoreFore ; (Allowing for pmFore)
_SaveBack ; And the same for the background
_RestoreBack
BRA.S @portWalkEnd
@oldPort
CMP.L portBits+baseAddr(A4),D1 ; same base on old port?
BNE.S @portWalkEnd
MOVE.L baseAddr(A3),portBits+baseAddr(A4)
MOVE rowBytes(A3),D1
AND #nurbMask,D1 ; handle NURBs here
MOVE D1,portBits+rowBytes(A4)
@portWalkEnd
DBRA D3,@portWalkLoop
MOVE.L oldPort(A6),-(SP) ; restore the pre-existing port
_SetPort
MOVE.L oldBaseAddr(A6),D1
CMP.L scrnBase,D1 ; fix scrnBase too, if neede
BNE.S @notMain
MOVE.L baseAddr(A3),scrnBase
@notMain
_AllocCursor
_ShowCursor
@noQD
;
; notify the Palette Manager that the mode has changed
;
; <2.6> moved after GDRect has been adjusted <2.6>
CMP.L #-1,PMgrHandle ; has the Palette Mgr been initialized?
BEQ.S @noPMgr ; nope, so skip this
MOVE.L GDH(A6),-(SP) ; push the device handle
_RestoreDeviceClut ; call the Palette Manager Unhook device vector
@noPMgr
MOVE.L SaveDevice(A6),theGDevice ; restore theGDevice
MOVE.L GDPMap(A2),A0 ; get pixMap handle
MOVE GDPState(A6),D0 ; get the lock state
_HSetState ; restore prior state
MOVE.L GDH(A6),A0 ; get the gDevice handle
MOVE GDHState(A6),D0 ; get the lock state
_HSetState ; restore prior state
MOVEM.L (SP)+,D3/A2-A4 ; restore work registers
UNLINK result-return-4,'INITGDEV'
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to InitPort. Add support for GDevices with baseAddrs that change across
; depths (Trident card) in a MultiFinder friendly way.
;
;=========================================================================================
;=========================================================================================
OpenPort PROC EXPORT
IMPORT NewPort,InsPortList
ciInsPortList EQU $319D0
ciNewPort EQU $316C0
;-------------------------------------------------------------
;
; PROCEDURE OpenPort(port: GrafPtr);
; { allocate clipRgn and visRgn, then call InitPort.
;
MOVE.L 4(SP),-(SP) ; push grafPort
MOVE.L (SP),-(SP) ; and a copy for InsPortList
jsrROM ciNewPort ; and init regions
jsrROM ciInsPortList ; add port to portlist
; fall into InitPort
EXPORT InitPort
InitPort ; <1.6>
;-------------------------------------------------------------
;
; PROCEDURE InitPort(port: GrafPtr);
;
; Initialize all fields of a grafPort
; Do fields used by cGrafPort first, then call routine for shared fields
;
ciROMGetDevPix EQU $28080
ciInitPortEntry EQU $31702
MOVE.L A2,-(SP) ; save work register
jsrROM ciROMGetDevPix ;GET DEVICE'S PIXMAP IN A0
MOVE.L 8(SP),A2 ; A2 = port param
LEA PORTBITS(A2),A1 ; POINT TO PORTBITS
MOVE PIXELSIZE(A0),D1 ;GET PIXEL DEPTH <BAL/KON> 17DEC89
MOVE.L (A0)+,(A1)+ ;COPY BASEADDR
MOVE (A0)+,D2 ;GET ROWBYTES
AND #nuRBMask,D2 ;CLEAR FLAG BITS
MOVE D2,D0 ;GET A COPY
EXT.L D0 ;MAKE SURE LONG FOR DIVIDE
DIVU D1,D0 ;PRETEND SCREEN IS ONE BIT DEEP
MOVE D0,(A1)+ ;COPY ROWBYTES
jmpROM ciInitPortEntry
; MOVE.L (A0),(A1)+ ;COPY BOUNDS.TOPLEFT
; MOVE.L 4(A0),(A1)+ ;COPY BOUNDS.BOTRIGHT <BAL/KON> 17DEC89
;
; JSR InitShared ; init shared fields
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to OpenCPort. If called from NewGWorld, save and restore thePort across
; the call.
;
;=========================================================================================
;=========================================================================================
;
; This patch is in PatchIIciROM.a
;
;=========================================================================================
;=========================================================================================
;
; GWorld patches follow. The equates for the GWorld stuff start here.
;
;=========================================================================================
;=========================================================================================
;___________________________________________________________________________
;
; QDExtensions Equates -- This file defines the public equates for QuickDraw
; extensions.
;___________________________________________________________________________
; New Error code
cDepthErr equ -157 ; invalid pixel depth
; Flag bits passed to NewGWorld
purgePixBit equ 0 ; make the offscreen buffer purgeable
noNewDeviceBit equ 1 ; don't create an offscreen device
useMFTempBit equ 2 ; allocate pixels in MFTemp memory <06Jul89> BAL
; Mask equivalents of the above bits
purgePixMask equ 1
noNewDeviceMask equ 2
useMFTempMask equ 4 ; <07Jul89> JCM
; Flag bits passed to or returned by UpdateGWorld
mapPixBit equ 16 ; set if color table mapping occurred
newDepthBit equ 17 ; set if pixels were scaled to a different depth
alignPixBit equ 18 ; set if pixels were realigned to screen alignment
newRowBytesBit equ 19 ; set if pixmap was reconfigured in a new rowBytes
reallocPixBit equ 20 ; set if offscreen buffer had to be reallocated
clipPixBit equ 28 ; set if pixels were or are to be clipped
stretchPixBit equ 29 ; set if pixels were or are to be stretched/shrinked
ditherPixBit equ 30 ; set if pixels were or are to be dithered
; Mask equivalents of the above bits
mapPixMask equ $10000
newDepthMask equ $20000
alignPixMask equ $40000
newRowBytesMask equ $80000
reallocPixMask equ $100000
clipPixMask equ $10000000
stretchPixMask equ $20000000
ditherPixMask equ $40000000
; Flag bits returned by GetPixelsState and passed to SetPixelsState
pixelsLockedBit equ 7 ; pixels are locked
pixelsPurgeableBit equ 6 ; pixels are purgeable
; Mask equivalents of the above bits
pixelsLockedMask equ $80
pixelsPurgeableMask equ $40
;___________________________________________________________________________
;
; Private equates for the additional field in the grafVars structure
;
;___________________________________________________________________________
attachDevice equ grafVarRec ; [4 bytes] handle to attached gDevice
devOwned equ attachDevice+4 ; [1 byte] true if NewGWorld created the offscreen device
useMFTemp equ devOwned+1 ; [1 byte] true if bits are in MultiFinder memory <07Jul89> JCM
grafVarExtRec equ useMFTemp+1 ; size of extended grafVars structure <07Jul89> JCM
; Bit in portVersion marking a CGrafPort as being a GWorld
isGWorldMask equ 1 ; bit 0 set means a CGrafPort is a GWorld
; If the portVersion/rowBytes of any port has the following bits set, it is a GWorld
GWorldFlag equ $C001 ; isPixMap+isCPort+isGWorld
; PixMaps in GWorlds have two possible version numbers
PixMapVers0 equ 0 ; marks that baseAddr is a 24-bit pointer <06Jul89> BAL
PixMapVers1 equ 1 ; marks that baseAddr is a clean derefed handle
PixMapVers2 equ 2 ; marks that baseAddr is a handle
PixMapVers4 equ 4 ; marks that baseAddr is a 32-bit pointer <06Jul89> BAL
PixMapVers1Bit equ 0 ; marks that baseAddr is a clean derefed handle
PixMapVers2Bit equ 1 ; marks that baseAddr is a handle
PixMapVers4Bit equ 2 ; marks that baseAddr is a 32-bit pointer <06Jul89> BAL
; As incredible as may seem, srcAverage is not defined in the includes used
; for building ROM or system code.
; srcAverage is used by MakeScaleTbl.
srcAverage equ $20 ; arithmetic mode average
; Define the constant nil to distinguish between scalars and pointers
IF &TYPE('Nil') = 'UNDEFINED' THEN
Nil: Equ 0
ENDIF
;=========================================================================================
;=========================================================================================
;
; Patch to NewGWorld. Selector 0 in QDExtDispatcher.
; If called with noNewDevice bit set, the pix map depth should be taken from the
; current device.
;
;=========================================================================================
;=========================================================================================
PatchNewGWorld PROC EXPORT
ciGetPixelDepthFromDevice EQU $3FBBA
ciCheckPixelShift EQU $3FBCA
ciParamError EQU $3FEE6
ciReportError EQU $3FEEE
ciBadPixelDepth EQU $3FEDE
ciFindMaxDevice EQU $3FB7C
;
; See description in GWorld.a
;
;----------------------------------------------------------------------------
;
; A6 offsets of parameters after link:
;
paramSize equ 22 ; size of parameters
result equ paramSize+8 ; WORD, QDErr
offscreenGWorld equ result-4 ; LONG, address of GWorldPtr variable
pixelDepth equ offscreenGWorld-2 ; WORD, pixel depth
boundsRect equ pixelDepth-4 ; LONG, address of bound Rectangle
cTable equ boundsRect-4 ; LONG, handle to color table
aGDevice equ cTable-4 ; LONG, handle to a device to use as model
theFlags equ aGDevice-4 ; LONG, flags
;----------------------------------------------------------------------------
;
; A6 offsets of local variables after link:
;
pixelShift equ -2 ; WORD, pixel shift amount
resPref equ pixelShift-2 ; WORD, device's preferred resolution
bytesPerRow equ resPref-2 ; WORD, rowBytes of offscreen pixmap
offscreenBufH equ bytesPerRow-4 ; LONG, handle to the offscreen buffer
offscreenPixMap equ offscreenBufH-4 ; LONG, handle to the offscreen pixmap
offscreenCTable equ offscreenPixMap-4 ; LONG, handle to the offscreen color table
offscreenDevice equ offscreenCTable-4 ; LONG, handle to the offscreen device
offscreenITable equ offscreenDevice-4 ; LONG, handle to the offscreen inverse table
offscreenPortH equ offscreenITable-4 ; LONG, handle to the offscreen port
offscreenPort equ offscreenPortH-4 ; LONG, pointer to the offscreen port
museDevice equ offscreenPort-4 ; LONG, handle to device used for inspiration
saveDevice equ museDevice-4 ; LONG, handle to previous current device
devType equ saveDevice-2 ; WORD, type of device
horizOffset equ devType-2 ; WORD, alignment of offscreen pixmap to screen
pixmapBounds equ horizOffset-8 ; Rect, rectangle describing pixmap bounds
localRect equ pixmapBounds-8 ; Rect, used for portRect (computed from boundsRect)
varSize equ localRect ; size of local variables
;----------------------------------------------------------------------------
link a6,#varSize ; allocate local variables
movem.l d3-d7/a2-a4,-(sp) ; save regs
;-------------------------------------------------------------------------
; Initialize the function result to no error. Optimistically assume that
; everything will go fine.
move #noErr,result(a6) ; flag a successful operation,
;-------------------------------------------------------------------------
; Initialize all offscreen local variables to zero.
; If an error happens during this function, we deallocate the memory for
; all allocated offscreen variables.
clr.l offscreenBufH(a6) ; handle to offscreen buffer
clr.l offscreenPixMap(a6) ; handle to offscreen pixmap
clr.l offscreenCTable(a6) ; handle to cloned color table
clr.l offscreenDevice(a6) ; handle to offscreen device
clr.l offscreenITable(a6) ; handle to offscreen device's inverse table
clr.l offscreenPortH(a6) ; handle to the offscreen port
;-------------------------------------------------------------------------
; Check that the boundsRect is not an empty rectangle.
; If it is empty, don't do anything.
;
clr.b -(sp) ; leave room for Boolean result
move.l boundsRect(a6),-(sp) ; push address of rectangle on the stack
_EmptyRect ; check if rectangle is empty or not
move.b (sp)+,d0 ; look at the result
bne paramError ; if true, boundsRect is empty, exit with error
;-------------------------------------------------------------------------
; Choose a device as our source of inspiration (muse) to determine
; default things like gdResPref, color table, etc.
; Use current device unless pixelDepth = 0 or noNewDeviceBit is set.
move.l theGDevice,museDevice(a6) ; get current device
;-------------------------------------------------------------------------
; Allocate memory for port. Do it early on to avoid heap fragmentation.
; Also, try to allocate it as low as possible in memory.
; No need to allocate a clear handle, it will be completely filled out by OpenCPort.
moveq #portRec,d0 ; size of CGrafPort
_ResrvMem ; reserve memory in lowest possible location
bne reportError ; if Memory Manager error, report it and quit
moveq #portRec,d0 ; size of CGrafPort
_NewHandle ; allocate a handle (no need to clear it)
bne reportError ; if Memory Manager error, report it and quit
move.l a0,offscreenPortH(a6) ; save handle to offscreen port
_HLock ; lock it down forever
move.l (a0),d0 ; get pointer to offscreen port
_StripAddress ; make it 32-bit fully clean
move.l d0,offscreenPort(a6) ; save it
; Initialize the portVersion field to 0. This field is used in case of
; memory error to check whether the port has been opened or not (and therefore
; I need to close it)
move.l d0,a0 ; get pointer to port
clr portVersion(a0) ; clear the portVersion field
;-------------------------------------------------------------------------
; Remember the theFlags in d3
move.l theFlags(a6),d3 ; remember for future use
;-------------------------------------------------------------------------
; Check range validity of pixelDepth -- it must be between 0 and 32.
move pixelDepth(a6),d7 ; pixel resolution
beq.s findMaxDevice ; if depth = 0, find max resolution
cmp #32,d7 ; illegal if > 32
bhi badPixelDepth ; exit with error
;-------------------------------------------------------------------------
; If pixelDepth is not 0, don't try to align offscreen pixmap to screen
clr horizOffset(a6) ; no alignment offset
;-------------------------------------------------------------------------
; Set localRect to the same as boundsRect (later use for portRect, etc.)
move.l boundsRect(a6),a0 ; get pointer to boundsRect
move.l topLeft(a0),localRect+topLeft(a6) ; copy boundsRect to localRect
move.l botRight(a0),localRect+botRight(a6)
; If noNewDeviceBit is set, use the given aGDevice as museDevice.
; Report an error if it is NIL.
btst.l #noNewDeviceBit,d3 ; is noNewDeviceBit set? (d3 contains the flags)
beq.s @0 ; no, leave museDevice as is
move.l aGDevice(a6),d0 ; yes, get aGDevice
beq.s paramError ; if aGDevice is NIL, report a parameter error
move.l d0,museDevice(a6) ; if not NIL, use it as muse Device
jmpROM ciGetPixelDepthFromDevice
; bra.s GetPixelDepthFromDevice ; take the pixel depth from the museDevice <KON 21JUN90>
@0
jmpROM ciCheckPixelShift
; bra.s checkPixelShift ; skip next part and check pixel resolution
paramError
jmpROM ciParamError
badPixelDepth
jmpROM ciBadPixelDepth
findMaxDevice
jmpROM ciFindMaxDevice
reportError
jmpROM ciReportError
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to UpdateGWorld. Selector 3 in QDExtDispatcher.
; Altered 'OR' (not MOVE) clip/stretch bit into result.
;
;=========================================================================================
;=========================================================================================
; This routine used to jump back into the ROM, but there are so many changes in so many
; places that I decided to patch the whole thing out. These ROM entry points were used.
; If disk space is extemely critical, some brave soul could convert it back.
;
;ciUpdateGWorld EQU $40290
;cinothingToDo EQU $403BA
;ciReallocBuffer EQU $403C2
;cimapColors EQU $404AC
;cirealignPixels EQU $403E6
;ciBadPixelDepth EQU $40A5A
;ciParamError EQU $40A8A
;ciROMShiftTable EQU $3FF3A
UpdateGWorld PROC EXPORT
EXPORT paramError
FINDINVERSETABLE EQU $3FF60
USEPALETTEMGR EQU 1
ciROMShiftTable EQU $3FF3A
;----------------------------------------------------------------------------
;
; FUNCTION UpdateGWorld (VAR offscreenGWorld: GWorldPtr; pixelDepth: INTEGER;
; boundsRect: Rect; cTable: CTabHandle; aGDevice: GDHandle;
; flags: LONGINT): LONGINT;
;
; Update the given graphics world to the new conditions (pixelDepth, boundsRect,
; color table, and optionally aGDevice).
;
; offscreenGWorld is both input and output. A pointer to the new GWorld is returned
; in offscreenGWorld.
;
; Flags determine how the pixels are preserved. It contains the following bits:
; clipPixBit = clip the pixels to the new boundsRect.
; stretchPixBit = stretch or shrink the pixels to the new boundsRect.
; ditherPixBit = dither the pixels
;
; clipPixBit and stretchPixBit are mutually exclusive.
; If flags is 0, no update occurs.
; Possible combinations are:
; 0, clipPixMask, stretchPixMask, clipPixMask+ditherPixMask, stretchPixMask+ditherPixMask
;
; PixelDepth, boundsRect, and cTable work in the same way as in NewGWorld.
;
; If aGDevice is not NIL, pixelDepth and cTable are ignored, and aGDevice's pixel depth
; and color table are used instead.
;
; If offscreenGWorld doesn't have an offscreen device and aGDevice is not NIL, aGDevice
; becomes the new attached device.
;
; UpdateGWorld returns an error code if it failed, 0 if it didn't do anything, and
; a positive number if it succeeded. This number describes what actions UpdateGWorld performed
; with the following bits:
;
; mapPixBit = set if color table mapping occurred
; newDepthBit = set if pixels were scaled to a different depth
; alignPixBit = set if pixels were realigned to screen alignment
; newRowBytesBit = set if pixmap was reconfigured in a new rowBytes
; reallocPixBit = set if offscreen buffer had to be reallocated
; clipPixBit = set if pixels were or are to be clipped
; stretchPixBit = set if pixels were or are to be stretched/shrinked
; ditherPixBit = set if pixels were or are to be dithered
;----------------------------------------------------------------------------
;
; A6 offsets of parameters after link:
;
paramSize equ 22 ; size of parameters
result equ paramSize+8 ; LONG, QDErr or flags
offscreenGWorld equ result-4 ; LONG, address of offscreen GWorldPtr variable
pixelDepth equ offscreenGWorld-2 ; WORD, new pixel depth
boundsRect equ pixelDepth-4 ; LONG, address of new bound Rectangle
cTable equ boundsRect-4 ; LONG, handle to new color table
aGDevice equ cTable-4 ; LONG, handle to device to use instead of pixelDepth and cTable
gDevflags equ aGDevice-4 ; LONG, defines pixel transfer
;----------------------------------------------------------------------------
;
; A6 offsets of local variables after link:
;
newGWorld equ -4 ; LONG, new offscreen GWorld
clipSrcRect equ newGWorld-8 ; Rect, srcRect clipped
clipDstRect equ clipSrcRect-8 ; Rect, same size as srcRect, but in dstRect coordinates
newFlags equ clipDstRect-4 ; LONG, contains purgePixBit and noNewDeviceBit
state equ newFlags-4 ; LONG, lock/purge state of pixels
purged equ state-1 ; BYTE, true if offscreen buffer has been purged
sameBounds equ purged-1 ; BYTE, true if the portRects of old and new gworlds are the same
mode equ sameBounds-2 ; WORD, transfer mode used by CopyBits
savePort equ mode-4 ; LONG, pointer to saved port
saveDevice equ savePort-4 ; LONG, handle to saved device
newBounds equ saveDevice-8 ; Rect, boundsRect converted to portRect
pixSize equ newBounds-2 ; WORD, pixel size of new offscreen gworld
colTabSeed equ pixSize-4 ; LONG, seed of new offscreen gworld's color table
horizOffset equ colTabSeed-2 ; WORD, alignment of new offscreen pixmap
newRowBytes equ horizOffset-2 ; WORD, rowBytes of new offscreen gworld
reserved equ newRowBytes-2 ; WORD, (match the ROM version of this stack frame)
saveStack equ reserved-4 ; LONG, copy of stack pointer after saving the register
maxDevice equ saveStack-4 ; LONG, handle to max device if pixelDepth = 0
newCTable equ maxDevice-4 ; LONG, handle to the new color table
newITable equ newCTable-4 ; LONG, handle to the new inverse table
resPref equ newITable-2 ; WORD, preferred resolution for inverse table
oldBufSize equ resPref-4 ; LONG, size of old offscreen buffer
saveForeColor equ oldBufSize-colorSpecSize ; ColorSpec, saved fg RGB color
saveBackColor equ saveForeColor-colorSpecSize ; ColorSpec, saved bk RGB color
saveClip equ saveBackColor-4 ; LONG, handle to saved clip region
varSize equ saveClip ; size of local variables
;----------------------------------------------------------------------------
link a6,#varSize ; allocate local variables
movem.l a2-a4/d5-d7,-(sp) ; save regs
move.l sp,saveStack(a6) ; save the stack pointer
;----------------------------------------------------------------------------
; Initialize the flags
clr.l result(a6) ; Assume no error and nothing to do
clr.l newFlags(a6) ; initialize flags for NewGWorld
; Check that no other bit than clipPixBit, stretchPixBit and ditherPixBit are set
move.l gDevFlags(a6),d0 ; get the flags
and.l #~(clipPixMask+stretchPixMask+ditherPixMask),d0 ; clear clipPixBit, stretchPixBit, ditherPixBit
tst.l d0 ; is any other bit set?
bne paramError ; yes, report a parameter error and quit
; Check that clipPixBit and stretchPixBit are not both set in the flags
move.l gDevFlags(a6),d0 ; get the flags
and.l #clipPixMask+stretchPixMask,d0 ; get clipPixBit and stretchPixBit
cmp.l #clipPixMask+stretchPixMask,d0 ; if both bit are set, quit with parameter error
beq paramError ; report error and quit
; Check that if ditherPixBit is set, one of clipPixBit or stretchPixBit is also set
move.l gDevFlags(a6),d0 ; get the flags
btst.l #ditherPixBit,d0 ; is ditherPixBit set?
beq getOffGWorld ; no, skip this
and.l #clipPixMask+stretchPixMask,d0 ; is one those bits set?
beq paramError ; nope, they're both 0, report error and quit
;----------------------------------------------------------------------------
; Remember pointer to offscreen GWorld
getOffGWorld
move.l ([offscreenGWorld,a6]),a3 ; get pointer to offscreen GWorld
; Save the current graphics world
pea savePort(a6) ; push address of savePort
pea saveDevice(a6) ; push address of saveDevice
_GetGWorld ; get current graphics world
;----------------------------------------------------------------------------
; If aGDevice is not NIL, use its depth and color table
checkAGDevice
move.l aGDevice(a6),d0 ; get handle to aGDevice
beq.s getNewParms ; it's NIL, don't do anything with it
move.l d0,a0 ; get handle in a0
move.l (a0),a0 ; get pointer to aGDevice
move.l ([gdPMap,a0]),a0 ; get pointer to its pixmap
move pixelSize(a0),pixelDepth(a6) ; use its pixelSize
move.l pmTable(a0),cTable(a6) ; and its color table
;----------------------------------------------------------------------------
; Compute new portRect and get new pixSize and color table seed for new offscreen graphics world
getNewParms
move.l boundsRect(a6),a0 ; get pointer to boundsRect
; Check range validity of pixelDepth -- it must be between 0 and 32.
move pixelDepth(a6),d7 ; pixel resolution
beq.s useMaxDevice ; if depth = 0, find max resolution
cmp #32,d7 ; illegal if > 32
bhi badPixelDepth ; exit with error
bra.s boundsIsLocal ; no, just copy boundsRect as is
;----------------------------------------------------------------------------
; If pixelDepth = 0:
; Offset boundsRect in newBounds so that topLeft = (0,0)
useMaxDevice
clr.l newBounds+topLeft(a6)
move bottom(a0),d0 ; compute newBounds.bottom = boundsRect->bottom - boundsRect->top
sub top(a0),d0
move d0,newBounds+bottom(a6)
move right(a0),d0 ; compute newBounds.right = boundsRect->right - boundsRect->left
sub left(a0),d0
move d0,newBounds+right(a6)
; Get pixSize from max device
clr.l -(sp) ; leave room for GDHandle result
move.l boundsRect(a6),-(sp) ; pass boundsRect as a global rect in screen space
_GetMaxDevice ; find deepest device that intersects boundsRect
move.l (sp)+,d0 ; get handle to max device <KON 6JUN90>
beq paramError ; if NIL, exit <KON 6JUN90>
move.l d0,a0 ; <KON 6JUN90>
move.l a0,maxDevice(a6) ; remember max device
move.l (a0),a1 ; get pointer to device
move.l ([gdPMap,a1]),a0 ; get pointer to its pixmap
move pixelSize(a0),pixSize(a6) ; get its pixel size
; Get color table seed from max device
move.l ([pmTable,a0]),a0 ; get pointer to color table
move.l ctSeed(a0),colTabSeed(a6) ; get its color table seed
; Get new pixmap alignment with the max device
move.l boundsRect(a6),a0 ; get pointer to boundsRect
move left(a0),d0 ; get left coordinate of boundsRect
sub gdRect+left(a1),d0 ; subtract left coordinate of device rectangle
move d0,horizOffset(a6) ; save offset
bra.s checkPixShift
;----------------------------------------------------------------------------
; If pixelDepth is not 0:
; Copy boundsRect to newBounds without modification
boundsIsLocal
move.l topLeft(a0),newBounds+topLeft(a6) ; copy boundsRect to newBounds
move.l botRight(a0),newBounds+botRight(a6)
; Alignment is 0
clr horizOffset(a6) ; no alignment if boundsRect is not global
; PixSize = pixelDepth
move pixelDepth(a6),pixSize(a6) ; if pixDepth is not 0, pixSize = pixelDepth
; If cTable is not 0, get its seed
move.l cTable(a6),d0 ; get handle to color table
beq.s noCTable ; if cTable is 0, use default seed
move.l d0,a0 ; get handle to color table
move.l (a0),a0 ; get pointer to color table
move.l ctSeed(a0),colTabSeed(a6) ; get color table seed
bra.s checkPixShift
; If cTable is 0, the color table seed is cmpCnt * cmpSize
noCtable
move pixelDepth(a6),d0 ; get pixel depth
cmp #16,d0 ; is it 16 bits/pixel?
bne.s check32 ; no, check to see if it is 32 bits/pixel
move #3*5,d0 ; if 16 bits/pixel, cmpCnt * cmpSize = 3 * 5
bra.s setCtSeed
check32 cmp #32,d0 ; is it 32 bits/pixel?
bne.s setCTSeed ; no, then pixelDepth = cmpCnt * cmpSize
move #3*8,d0 ; if 32 bits/pixel, cmpCnt * cmpSize = 3 * 8
setCtSeed
ext.l d0 ; convert to long
move.l d0,colTabSeed(a6) ; remember color table seed
;----------------------------------------------------------------------------
; Convert pixel depth to shift amount
; Use ShiftTbl for conversion
checkPixShift
move pixSize(a6),d7 ; get pixel size
leaROM ciROMShiftTable,a0 ; table to convert pixSize to pixelShift (exponent of 2)
moveq #0,d0 ; clear high byte
move.b 0(a0,d7),d7 ; fetch table
bmi badPixelDepth ; if table returned -1, pixelDepth is invalid, exit w/error
; Convert horizOffset to a number of pixels such that the equivalent number of bits is modulo 32
move horizOffset(a6),d0 ; get horizontal offset in pixels
lsl d7,d0 ; convert to bits
and #$1f,d0 ; offset modulo 32
lsr d7,d0 ; convert back to pixels
move d0,horizOffset(a6) ; save back in horizOffset <19Jun89> JCM
;----------------------------------------------------------------------------
; Get rowBytes from old pixmap, assume it will not change
move.l ([portPixMap,a3]),a0 ; get pointer to old pixmap
move rowBytes(a0),d0 ; get rowBytes
and #nuRBMask,d0 ; strip off flags
move d0,newRowBytes(a6) ; assume rowBytes doesn't change
;----------------------------------------------------------------------------
; Compare the portRects of the old and new world.
; If same, set the sameBounds flag
clr.b sameBounds(a6) ; assume portRects are different
move.l portRect+topLeft(a3),d0 ; get the topLeft coordinates of the old gworld
cmp.l newBounds+topLeft(a6),d0 ; compare with topLeft coordinates of new gworld
bne.s compareSize
move.l portRect+botRight(a3),d0 ; get the botRight coordinates of the old gworld
cmp.l newBounds+botRight(a6),d0 ; compare with botRight coordinates of new gworld
bne.s compareSize
move.b #true,sameBounds(a6) ; rectangles are equal, set the sameBounds flag
bra checkAlignment ; skip comparing size
;----------------------------------------------------------------------------
; If different size, set clipPixBit or stretchPixBit depending on flags
compareSize
move portRect+right(a3),d0 ; calculate old port's width (a3 = old GWorldPtr)
sub portRect+left(a3),d0
move newBounds+right(a6),d1 ; calculate new port's width
sub newBounds+left(a6),d1
cmp d0,d1 ; are widths the same?
bne.s checkRowBytes ; no, check the rowBytes
move portRect+bottom(a3),d0 ; calculate old port's height
sub portRect+top(a3),d0
move newBounds+bottom(a6),d1 ; calculate new port's height
sub newBounds+top(a6),d1
cmp d0,d1 ; are heights the same?
beq.s checkAlignment ; yes, portRect's are same size, no clipping/stretching
;----------------------------------------------------------------------------
; Compute rowBytes of new world.
; Compare the rowBytes of the old and new world.
; If different, set newRowBytes bit
; Then, set the clipPixBit or stretchPixBit
checkRowBytes
move newBounds+right(a6),d0 ; compute pixmap.bounds.right - pixmap.bounds.left
sub newBounds+left(a6),d0 ; don't take into account alignment
;-------------------------------------------------------------------------
; Allocate the actual offscreen buffer.
; rowBytes is computed as the smallest number of longs containing one line of pixel + 31 bits,
; converted to bytes:
; (((localRect.right - localRect.left) * pixelSize + 31 + 31) / 32) * 4
;
; NOTE 1: Adding 31 bits gives us some leg room if we want to realign the pixmap in UpdateGWorld.
; The additional 31 bits are to force a round-up top the next long (as usual).
; NOTE 2: localRect is used instead of pixmapBounds because rowBytes is computed independently
; of the current alignment but for all possible alignments.
; NOTE 3: The above formula for rowBytes can be simplified in:
; (((localRect.right-localRect.left) * pixelSize + 30) / 32 + 1) * 4
ext.l d0 ; convert to long
lsl.l d7,d0 ; convert pixels to bits (pixShift is in d7)
add.l #30,d0 ; add 30 bits as per simplified formula above
lsr.l #5,d0 ; convert bits to longs
addq #1,d0 ; add one long as per simplified formula above
lsl.l #2,d0 ; convert longs to bytes
move d0,newRowBytes(a6) ; save # of bytes in a row
; Compare the rowBytes of the old and new world and set the newRowBytesBit if different
move.l ([portPixMap,a3]),a0 ; get pointer to old pixmap
move rowBytes(a0),d1 ; get rowBytes
and #nuRBMask,d1 ; mask out flags
cmp d1,d0 ; if different, set newRowBytes bit
beq.s setClipStretchBit ; same rowBytes, don't set newRowBytes bit
or.l #newRowBytesMask,result(a6) ; set newRowBytes bit
;----------------------------------------------------------------------------
; PortRects of old and new world are of different sizes, decide between clip and stretch
setClipStretchBit
move.l gDevFlags(a6),d0 ; get flags
and.l #clipPixMask,d0 ; is the clipPixBit set?
bne.s @0 ; yes, use clipping
move.l #stretchPixMask,d0 ; no, use stretching
@0
or.l d0,result(a6) ; store bits in result <1.6>
;----------------------------------------------------------------------------
; Compare the left coordinates of the portPixMap->bounds of the old and new world.
; If different, assume alignment is taking place (don't bother getting with
; max area device and checking that alignment might still be the same)
checkAlignment
move.l ([portPixMap,a3]),a0 ; get pointer to old pixmap
move bounds+left(a0),d0 ; get bounds.left of old pixmap
move horizOffset(a6),d1 ; get alignment of new pixmap
neg d1 ; the algebraic opposite is the bounds.left of the new pixmap
cmp d1,d0 ; compare them both
beq.s checkPixelDepth ; identical, no alignment
or.l #alignPixMask,result(a6) ; different, set alignment bit
;----------------------------------------------------------------------------
; Compare the pixel depths of the old and new world. If different, set the scalePixelsBit
checkPixelDepth
move #srcCopy,mode(a6) ; initialize transfer mode to srcCopy
move.l ([portPixMap,a3]),a0 ; get pointer to old pixmap again (if got here directly)
move pixelSize(a0),d0 ; get pixel size of old pixmap
cmp pixSize(a6),d0 ; compare with pixel size of new pixmap
beq.s checkColTable ; identical, no scaling
or.l #newDepthMask,result(a6) ; different, set scaling bit
move.l gDevFlags(a6),d0 ; get flags
and.l #ditherPixMask,d0 ; get dither bit
beq.s @0 ; dither bit not set, don't change transfer mode
move #64,mode(a6) ; dither bit set, use dither mode
or.l #ditherPixMask,result(a6) ; and set ditherPixBit in result
@0
;----------------------------------------------------------------------------
; Compare the color table seeds. If different, set the mapPixelsBit
checkColTable
move.l ([pmTable,a0]),a0 ; get pointer to old color table
move.l ctSeed(a0),d0 ; get old seed
cmp.l colTabSeed(a6),d0 ; compare with new seed
beq.s getState ; identical, no color mapping
or.l #mapPixMask,result(a6) ; different, set mapping bit
;----------------------------------------------------------------------------
; Get state of offscreen buffer
getState
clr.l -(sp) ; leave room for flags result
move.l portPixMap(a3),-(sp) ; push handle to pixmap
_GetPixelsState ; get state of pixels
move.l (sp)+,d0 ; get the result
move.l d0,state(a6) ; remember it for later
; Prevent purging of the offscreen buffer for the time of UpdateGWorld
move.l portPixMap(a3),-(sp) ; push handle to pixmap
_NoPurgePixels ; don't purge the pixels
;----------------------------------------------------------------------------
; Set purgePixBit in the flags for NewGWorld if the pixels are purgeable or purged
; Set reallocPixBit in the result of UpdateGWorld if the pixels are purged
clr.b purged(a6) ; assume pixels aren't purged
clr.l -(sp) ; leave room for Ptr result
move.l portPixMap(a3),-(sp) ; push handle to pixmap
_GetPixBaseAddr ; get address of offscreen buffer
move.l (sp)+,d0 ; put it in d0
bne.s notPurged ; offscreen buffer hasn't been purged
or.l #purgePixMask,newFlags(a6) ; offscreen buffer is purged, it means it's purgeable
or.l #reallocPixMask,result(a6) ; flag that we had to reallocate the pixels
; Remember that offscreen buffer is purged.
; GetPixelsState returns an error if the offscreen buffer is purged.
; Changed the result of GetPixelsState to a long with the purge bit set.
; (lock bit wasn't set before the purge or buffer wouldn't have been purged)
move.b #true,purged(a6) ; remember that offscreen buffer is purged
move.l #pixelsPurgeableMask,state(a6) ; if the pixels are purged, recompute state
bra.s testNoDevice
notPurged
move.l state(a6),d0 ; get the state of the pixels
btst.l #pixelsPurgeableBit,d0 ; is the pixelsPurgeableBit set?
beq.s testNoDevice ; no, don't set purgePixBit in the flags
or.l #purgePixMask,newFlags(a6) ; offscreen buffer is purgeable, set the purgePixBit
; If the attached device is not owned by the offscreen GWorld,
; set noNewDeviceBit in the flags for NewGWorld.
testNoDevice
move.l ([grafVars,a3]),a0 ; get pointer to grafVars (a3 = old GWorldPtr)
move.b devOwned(a0),d0 ; get devOwned flag
bne.s testMFTempPixels ; device is owned, don't set noNewDeviceBit <07Jul89> JCM
or.l #noNewDeviceMask,newFlags(a6) ; device is not owned, set noNewDeviceBit
; If the pixels are allocated in MultiFinder temp memory (as indicated in the <07Jul89> JCM
; grafVars), set the useMFTempBit in the flags for NewGWorld. <07Jul89> JCM
testMFTempPixels
tst.b useMFTemp(a0) ; test useMFTemp flag in grafVars <07Jul89> JCM
beq.s dispatchFlags ; not set, don't set useMFTempBit <07Jul89> JCM
or.l #useMFTempMask,newFlags(a6) ; set useMFTempBit <07Jul89> JCM
;----------------------------------------------------------------------------
; Look at the result flags and find if we can use optimized algorithms
; Currently optimized cases are:
; 0. Nothing needs to be done (just exit and return 0)
; 1. Pixels have been purged (nothing else changes)
; 2. Color Table changes (nothing else changes, not even pixel depth)
; 3. Pixels need to be realigned (but boundsRect's size doesn't change)
dispatchFlags
move.l result(a6),d0 ; get the result flags
beq.s nothingToDo ; if no bit set, there is nothing to do
cmp.l #reallocPixMask,d0 ; is reallocPixBit the only bit set?
beq.s reallocBuffer ; yes, just reallocate the offscreen buffer
; The following cases are relevant only if the pixels are to be preserved
; If the pixels are not to be preserved, just dispose of the old gworld and create a new one
tst.l gDevFlags(a6) ; is any update flag set?
beq updatePixels ; nope, go dispose of old gworld and create a new one
cmp.l #mapPixMask,d0 ; is mapPixBit the only bit set?
bne.s @0 ; no, can't just do color mapping
tst.b sameBounds(a6) ; are the bounds of both gworlds the same
beq.s @0 ; no, can't just do color mapping
cmp #4,d7 ; is the pixel resolution <16 (pixShift < 4)
blt mapColors ; yes, just have to do a color mapping with same pixel depth
@0
cmp.l #alignPixMask,d0 ; is alignPixBit the only bit set?
beq.s realignPixels ; yes, just realign the pixels and pixmap
bra updatePixels ; none of these cases apply, use regular case
;----------------------------------------------------------------------------
; Nothing at all has changed in the offscreen gworld.
nothingToDo
move.l a3,newGWorld(a6) ; that's it, we already have the new gworld
bra setState ; set the state of the offscreen buffer and quit
;----------------------------------------------------------------------------
; Nothing has changed in the offscreen gworld except that the pixels have been purged
; Reallocate them and put the handle in the baseAddr of the pixmap.
; NOTE: If the pixels are purged, the pmVersion of the pixmap is always PixMapVers2 (LockPixels
; doesn't set the pmVersion to PixMapVers1 if the pixels are purged), therefore, the handle
; is the appropriate thing to put in the baseAddr.
reallocBuffer
move newBounds+bottom(a6),d0 ; compute height = bottom-top
sub newBounds+top(a6),d0
mulu.w newRowBytes(a6),d0 ; compute height * rowBytes
move.l ([portPixMap,a3]),a1 ; get pointer to offscreen pixmap <06Jul89> BAL
move.l baseAddr(a1),a0 ; get handle to offscreen buffer from offscreen pixmap <06Jul89> BAL
_ReallocHandle ; allocate offscreen buffer (could be in MFTemp memory) <06Jul89> BAL
bne reportError ; if Memory Manager error, report it and quit
_MoveHHi ; move the buffer as high as possible in memory
move.l a3,newGWorld(a6) ; that's it, we already have the new gworld
bra setState ; set the state of the offscreen buffer and quit
;----------------------------------------------------------------------------
; Nothing has changed in the offscreen gworld except that the boundsRect
; has been moved around (while keeping the same size).
; The algorithm realigns all the pixels. No mask is used for the edges because they
; contain unused pixels.
realignPixels
; Get the address of the pixels
clr.l -(sp) ; leave room for Ptr result
move.l portPixMap(a3),-(sp) ; push handle to pixmap
_GetPixBaseAddr ; get address of pixels
move.l (sp)+,a1 ; keep address in a1
; Get pointer past end of pixels
move newBounds+bottom(a6),d0 ; compute height
sub newBounds+top(a6),d0
move newRowBytes(a6),d1 ; get rowBytes
mulu.w d1,d0 ; compute size of offscreen buffer
move.l a1,a4 ; get starting address
add.l d0,a4 ; compute end of offscreen buffer + 1
; Compute alignment difference between old gworld and new gworld:
move.l ([portPixMap,a3]),a0 ; get pointer to offscreen pixmap
move bounds+left(a0),d6 ; get left coordinate (= -alignment)
neg d6 ; get old alignment
sub horizOffset(a6),d6 ; subtract new alignment
ext.l d6 ; convert to long
lsl.l d7,d6 ; convert from pixels to bits
blt.s goBackwards ; go backwards if alignment difference negative
; If alignment difference is positive, go from beginning to end of buffer
@nxtLong
bfextu (a1){d6:0},d0 ; get one long of pixels at new alignment
move.l d0,(a1)+ ; store back in pixmap in the correct location
cmp.l a4,a1 ; are we at the limit?
blt.s @nxtLong ; no, get a new long and continue
bra.s updateTheRects ; go update the pixmap's bounds, portRect and gdRect
; If alignment difference is negative, go from end to beginning of buffer
goBackwards
sub.l #32,d6 ; extract at one long earlier because of the predecrement used below
@nxtLong
bfextu (a4){d6:0},d0 ; get one long of pixels at new alignment
move.l d0,-(a4) ; store back in pixmap in the correct location
cmp.l a4,a1 ; have we reached the beginning of the buffer?
blt.s @nxtLong ; no, continue
; Update the port pixmap's bounds to the newBounds with alignment
updateTheRects
move.l ([portPixMap,a3]),a0 ; get pointer to pixmap
move newBounds+top(a6),bounds+top(a0) ; put new bounds.top
move newBounds+left(a6),d0 ; compute left coordinate with alignment
sub horizOffset(a6),d0
move d0,bounds+left(a0) ; put new bounds.left
move.l newBounds+botRight(a6),bounds+botRight(a0) ; put new bounds.botRight
; Update the port's portRect to the newBounds without alignment
move.l newBounds+topLeft(a6),portRect+topLeft(a3) ; copy newBounds to portRect
move.l newBounds+botRight(a6),portRect+botRight(a3)
; Set visible region of offscreen port to portRect
move.l visRgn(a3),-(sp) ; push handle to visRgn
pea portRect(a3) ; push address of portRect
_RectRgn ; make visRgn = portRect
; Return the old GWorld into the newGWorld
move.l a3,newGWorld(a6) ; GWorld hasn't changed
; If the attached device is owned by the GWorld, update its pixmap's bounds and gdRect
move.l ([grafVars,a3]),a1 ; get pointer to grafVars (a3 = old GWorldPtr)
move.b devOwned(a1),d0 ; get devOwned flag
beq setState ; device is not owned, we're done, go set the pixels' state and quit
move.l ([attachDevice,a1]),a1 ; get the pointer to the offscreen device attached
move.l bounds+topLeft(a0),gdRect+topLeft(a1) ; copy port's pixmap's bounds to gdRect
move.l bounds+botRight(a0),gdRect+botRight(a1)
move.l ([gdPMap,a1]),a1 ; get pointer to device's pixmap
move.l bounds+topLeft(a0),bounds+topLeft(a1) ; copy port's pixmap's bounds to device's pixmap's bounds
move.l bounds+botRight(a0),bounds+botRight(a1)
bra setState ; we're done, go set the state of the offscreen buffer and quit
;----------------------------------------------------------------------------
; Nothing has changed in the offscreen gworld except the color table
; Do things differently if the gworld owns the attached device or not
mapColors
move.l theGDevice,saveDevice(a6) ; save the current device
move.l a3,newGWorld(a6) ; new offscreen gworld is same as old one
move.l ([grafVars,a3]),a4 ; get pointer to grafVars structure
; Set the current GWorld to the old (same as new) GWorld for Palette Manager calls
move.l a3,-(sp) ; push pointer to old offscreen gworld
clr.l -(sp) ; use attached device
_SetGWorld ; set current port and device to old world
;----------------------------------------------------------------------------
; Save Foreground and Background colors before the color mapping
; If Palette Manager is there, use SaveFore and SaveBack to save fg and bk colors
if UsePaletteMgr then
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_SaveFore ; get foreground color from Palette Manager
pea saveBackColor(a6) ; push address of saved background ColorSpec
_SaveBack ; get background color from Palette Manager
; If Palette Manager is not there, use GetForeColor and GetBackColor instead
else
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_GetForeColor ; get foreground color from port
pea saveBackColor(a6) ; push address of saved background ColorSpec
_GetBackColor ; get background color from port
endif
; Check whether the attached device was created by NewGWorld or not
move.l newFlags(a6),d0 ; get the flags for NewGWorld
and.l #noNewDeviceMask,d0 ; extract noNewDeviceBit
beq.s updateDevice ; noNewDeviceBit is clear, update the existing attached device
;----------------------------------------------------------------------------
; If the noNewDeviceBit is set in the flags for NewGWorld:
; set aGDevice as the new current device
; call MakeScaleTbl to make a scale table between the old and the new color table
; dispose of the old device (if previous current device was old device, change it to aGDevice)
; use aGDevice as the new attached device
; put the handle to the new color table into the port's pixmap's pmTable field
move.l aGDevice(a6),theGDevice ; set aGDevice as the new current device
move.l ([portPixMap,a3]),-(sp) ; push pointer to offscreen pixmap
move #srcAverage,-(sp) ; pass srcAverage as the mode for MakeScaleTbl
_MakeScaleTbl ; create a scale table for color mapping
move.l attachDevice(a4),a0 ; get handle to currently attached device
move.l saveDevice(a6),a1 ; get handle to saved device
cmp.l a0,a1 ; was this the previous current device
bne.s @0 ; no, just get rid of it
move.l aGDevice(a6),saveDevice(a6) ; yes, then replace it with aGDevice
@0
move.l a0,-(sp) ; push handle to attached device
_DisposGDevice ; get rid of it (including color table referenced by pixmap)
move.l aGDevice(a6),a0 ; get handle to aGDevice
move.l a0,attachDevice(a4) ; use aGDevice as the new attached device
move.l (a0),a0 ; get pointer to new attached device
move.l ([gdPMap,a0]),a0 ; get pointer to its pixmap
move.l ([portPixMap,a3]),a1 ; get pointer to old pixmap
move.l pmTable(a0),pmTable(a1) ; copy color table handle (share actual color table with device)
move.l saveDevice(a6),theGDevice ; restore current device
bra mapThePixels ; go use the scale table to map the pixels
;----------------------------------------------------------------------------
; If the noNewDeviceBit is clear:
; get the new color table and put its reference in the attached device's pixmap
; get or create an inverse table for the color table
; set the attached device as the new current device
; call MakeScaleTbl to make a scale table between the old and the new color table
; get rid of the old color table
; put the handle to the new color table into the port's pixmap's pmTable field
updateDevice
; Get preferred resolution for inverse table from the attached device
move.l ([attachDevice,a4]),a0 ; get pointer to attached device
move gdResPref(a0),resPref(a6) ; get preferrred resolution
move.l cTable(a6),a0 ; get color table handle
clr.l newITable(a6) ; initialize handle to inverse table
; If pixelDepth = 0, ignore cTable, copy color table from museDevice
tst pixelDepth(a6) ; is pixelDepth 0?
beq.s getFromMax ; yes, get color table from maxDevice
; If cTable is not nil, clone it
cmp.l #nil,a0 ; if cTable is not nil,
bne.s cloneCTab ; just clone it
; if cTable is nil and pixelDepth <> 0, get default color table for pixelDepth
clr.l -(sp) ; leave room for CTabHandle result
move pixelDepth(a6),-(sp) ; use pixelDepth as ID
_GetCTable ; get a copy of the system color table for pixelDepth
move.l (sp)+,a0 ; get handle to color table
tst.l a0 ; was the call successful?
beq getCTabError ; no, report an error in GetCTable
bra.s dontCloneCTab ; color table from GetCTable is already a copy, don't clone it
; If pixelDepth = 0, get color table and inverse table from the max gDevice
getFromMax
move.l ([maxDevice,a6]),a0 ; get the master pointer to the device
move.l gdITable(a0),newITable(a6) ; get its inverse table handle and save it
move.l ([gdPMap,a0]),a0 ; get the master pointer to its pixmap
move.l pmTable(a0),a0 ; get the color table handle
; Clone the color table
cloneCTab
_HandToHand ; color table handle is in a0
bne reportError ; if Memory Manager error, report it and quit
; Store handle to color table in pixmap
dontCloneCTab
move.l a0,newCTable(a6) ; save cloned color table handle
;-------------------------------------------------------------------------
; Create an inverse table for the offscreen color table.
; If the color table came from an existing device, we already have the inverse
; table.
; If we don't have the inverse table yet, scan the DeviceList for a device
; that might have the same color table.
; If still unsuccessful, we have to call MakeITable.
; If we got the inverse table for free (from maxDevice), just clone it.
; At this point, newITable hasn't been cloned yet.
move.l newITable(a6),a0 ; get handle to offscreen inverse table
tst.l a0 ; is it nil?
bne.s cloneITab ; no, we already have it, just clone it
; Scan device list to find a device with same color table
clr.l -(sp) ; leave room for ITabHandle result
move.l newCTable(a6),-(sp) ; push handle to color table
jsrROM FindInverseTable ; find corresponding inverse table in the device list
move.l (sp)+,a0 ; get ITabHandle result
tst.l a0 ; if we found an already built inverse table,
bne.s cloneITab ; clone it
; Allocate inverse table to its initial size
moveq #2,d0 ; initial size is 2
_NewHandle ,CLEAR ; allocate it
bne reportError ; if Memory Manager error, report it and quit
move.l a0,newITable(a6) ; save handle to inverse table
; Build Inverse Table
move.l newCTable(a6),-(sp) ; push handle to offscreen color table
move.l a0,-(sp) ; push handle to offscreen inverse table
move resPref(a6),-(sp) ; push inverse table resolution
_MakeITable ; build inverse table
move QDErr,d0 ; check for MakeITable errors (in QDErr)
bne makeITabError ; report error and quit
bra.s storeInDevice ; go update the offscreen device
; Clone inverse table if not created by MakeITable
cloneITab
_HandToHand ; inverse table handle is in a0, clone it
bne reportError ; if Memory Manager error, report it and quit
move.l a0,newITable(a6) ; save handle to cloned inverse table
storeInDevice
move.l ([grafVars,a3]),a4 ; get pointer to grafVars structure
move.l ([attachDevice,a4]),a0 ; get pointer to attached device <19Jun89> JCM
move.l gdITable(a0),a0 ; get handle to current inverse table <19Jun89> JCM
_DisposHandle ; get rid of it <19Jun89> JCM
move.l ([attachDevice,a4]),a0 ; get pointer to attached device
move.l newITable(a6),gdITable(a0) ; store handle to new inverse table in device
move.l ([gdPMap,a0]),a0 ; get handle to device's pixmap
move.l newCTable(a6),pmTable(a0) ; store handle to new color table in device
move.l attachDevice(a4),theGDevice ; set attached device as new current device for MakeScaleTbl
move.l ([portPixMap,a3]),-(sp) ; push pointer to offscreen pixmap
move #srcAverage,-(sp) ; pass srcAverage as the mode for MakeScaleTbl
_MakeScaleTbl ; create a scale table for color mapping
move.l saveDevice(a6),theGDevice ; restore current device
move.l ([portPixMap,a3]),a4 ; get pointer to offscreen pixmap
move.l pmTable(a4),a0 ; get handle to old color table
_DisposHandle ; get rid of it
move.l newCTable(a6),pmTable(a4) ; store handle to new color table into old pixmap
;----------------------------------------------------------------------------
; Use the scale table to map the pixels to the new color table
mapThePixels
; First check that the scale table is not identical
; If identical, don't have to do anything!
@chkTbl moveq #1,d0 ; # entries = 2^ pixelSize
move pixSize(a6),d7 ; get pixel size
lsl d7,d0 ; calc # entries in d0
clr.l d1 ; clear upper-half of d1 <20Jun89> JCM
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.l d1,a0 ; point past end of table
@1 cmp.l -(a0),d0 ; compare with dst pixel value
dbne d0,@1
beq setState ; tables are equal, we're done, go set the state of the pixels
; Tables are not equal, do the mapping
; Get initial parameters:
; a1 = pointer to the beginning of the pixels
; a4 = pointer past the end of the pixels
; d1 = $1f (mask for longs)
; d6 = pixel offset into one long of pixels
; d7 = pixel size
; sp = pointer to scale table
;
; The algorithm maps all the pixels (even the ones on the edges).
; The pixels on the edges should not be changed (index 0 typically stays black in all color tables)
; Even if the pixels on the edges change, they're not used anyway (so why bother...)
clr.l -(sp) ; leave room for Ptr result
move.l portPixMap(a3),-(sp) ; push handle to pixmap
_GetPixBaseAddr ; get address of pixels
move.l (sp)+,a1 ; keep address in a1
move.l ([portPixMap,a3]),a0 ; get pointer to offscreen pixmap
move rowBytes(a0),d1 ; get rowBytes
and #nuRBMask,d1 ; get rid of flags
move bounds+bottom(a0),d0 ; compute height
sub bounds+top(a0),d0
mulu.w d1,d0 ; compute size of offscreen buffer
move.l a1,a4 ; get starting address
add.l d0,a4 ; compute end of offscreen buffer + 1
; Start loop
moveq #0,d6 ; initialize pixel offset within a long of pixels
moveq #$1f,d1 ; get mask for longs
@nxtLong
move.l (a1),d5 ; get one long of pixels
@nxtPixel
bfextu d5{d6,d7},d0 ; get one pixel
move.l 0(sp,d0*4),d0 ; translate it
bfins d0,d5{d6,d7} ; insert translated pixel into long
add d7,d6 ; bump to next pixel
and d1,d6 ; time for next long?
bne.s @nxtPixel ; no, do next pixel
move.l d5,(a1)+ ; yes, save current long
cmp.l a4,a1 ; have we reached the limit?
blt.s @nxtLong ; no, get a new long and continue
;----------------------------------------------------------------------------
; Update foreground and background colors to new color table
; If Palette Manager is there, use RestoreFore and RestoreBack to restore fg and bk colors
if UsePaletteMgr then
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_RestoreFore ; set foreground color with Palette Manager call
pea saveBackColor(a6) ; push address of saved background ColorSpec
_RestoreBack ; set background color with Palette Manager call
; If Palette Manager is not there, use RGBForeColor and RGBBackColor instead
else
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_RGBForeColor ; set foreground color
pea saveBackColor(a6) ; push address of saved background ColorSpec
_RGBBackColor ; set background color
endif
bra setState ; we're done, go set the state of the offscreen buffer and quit
;----------------------------------------------------------------------------
; Create a new graphics world and, if necessary, CopyBits the old graphics world into the new one
updatePixels
; Update the flags in result according to the update flags passed to UpdateGWorld
; We're going to realloc the offscreen
or.l #reallocPixMask,result(a6) ; flag that we had to reallocate the pixels
; If the attached device is owned by the offscreenGWorld,
; we don't need aGDevice anymore (we'll create a new one with NewGWorld)
move.l newFlags(a6),d0 ; get the flags for NewGWorld
and.l #noNewDeviceMask,d0 ; extract the noNewDeviceBit
bne.s testUpdate ; if bit is set, pass aGDevice to NewGWorld
clr.l aGDevice(a6) ; if bit is clear, clear aGDevice so that NewGWorld create a new device
;----------------------------------------------------------------------------
; Dispose of old offscreen buffer if no CopyBits will take place.
; Don't dispose of the old graphics world (in case NewGWorld fails).
testUpdate
clr.l oldBufSize(a6) ; initialize to 0 (assume old offscreen not disposed of)
tst.b purged(a6) ; are the pixels purged?
bne.s @0 ; yes, dispose of the old graphics world
move.l gDevFlags(a6),d0 ; get flags
bne.s createNew ; if there is update to do, don't dispose old GWorld
@0
move.l portPixMap(a3),a4 ; get handle to old pixmap
move.l a4,-(sp) ; push it
_UnlockPixels ; unlock pixels so we have a handle in baseAddr
move.l (a4),a1 ; get pointer to pixmap
move.l baseAddr(a1),a4 ; get handle to offscreen buffer
clr.l baseAddr(a1) ; clear it to mark that it's disposed
move.l a4,a0 ; get offscreen buffer handle in a0
_GetHandleSize ; get size of offscreen buffer
move.l d0,oldBufSize(a6) ; remember it in case NewGWorld fails
move.l a4,a0
_DisposHandle ; get rid of old offscreen buffer
;----------------------------------------------------------------------------
; Create a new graphics world
createNew
clr -(sp) ; leave room for result
pea newGWorld(a6) ; push address of new offscreen GWorldPtr variable
move pixelDepth(a6),-(sp) ; new pixel depth
move.l boundsRect(a6),-(sp) ; new bound rectangle
move.l cTable(a6),-(sp) ; new color table
move.l aGDevice(a6),-(sp) ; pass aGDevice (NIL if noNewDeviceBit is clear)
move.l newFlags(a6),-(sp) ; flags with appropriate noNewDeviceBit and purgePixBit
_NewGWorld ; create a new GWorld
move (sp)+,d0 ; look at result
bne newGWorldError ; an error happened, handle it properly
;----------------------------------------------------------------------------
; Update new grafport with fields from old grafport
move.l newGWorld(a6),a4 ; get pointer to new grafport
move chExtra(a3),chExtra(a4) ; copy fields that should be remembered
move pnLocHFrac(a3),pnLocHFrac(a4)
; Update clipRgn by:
; offsetting it to the new portRect if clipPixBit set
; mapping it to the new portRect if stretchPixBit set
move.l clipRgn(a3),-(sp) ; first copy clip region
move.l clipRgn(a4),-(sp)
_CopyRgn
; Compare the rowBytes of the old and new world and set the newRowBytesBit if different
move.l ([portPixMap,a3]),a0 ; get pointer to old pixmap
move rowBytes(a0),d0 ; get rowBytes
and #nuRBMask,d0 ; mask out flags
move.l ([portPixMap,a4]),a0 ; get pointer to old pixmap
move rowBytes(a0),d1 ; get rowBytes
and #nuRBMask,d1 ; mask out flags
cmp d1,d0 ; if different, set newRowBytes bit
beq.s @RowBytesFlagDone ; same rowBytes, don't set newRowBytes bit
or.l #newRowBytesMask,result(a6) ; set newRowBytes bit
@RowBytesFlagDone
move.l gDevFlags(a6),d0 ; get the flags
and.l #clipPixMask,d0 ; look at the clipPixBit
bne offsetClip ; clipPixBit set, offset the clip region
move.l clipRgn(a4),-(sp) ; push handle to clip Region
pea portRect(a3) ; push address of old portRect
pea portRect(a4) ; push address of new portRect
_MapRgn ; map region from old portRect to new portRect
bra copyPixPats
; Offset clipRgn to the new portRect
offsetClip
move.l clipRgn(a4),-(sp) ; push handle to clip Region
move portRect+left(a4),d0 ; compute offset between left coordinates of old and new portRect
sub portRect+left(a3),d0
move d0,-(sp)
move portRect+top(a4),d0 ; compute offset between top coordinates of old and new portRect
sub portRect+top(a3),d0
move d0,-(sp)
_OfsetRgn ; offset the region
; Copy the pixel patterns, pen characteristics, etc.
copyPixPats
move.l bkPixPat(a3),d0 ; get old background pixel pattern
beq noBkPixPat ; if it is NIL, don't copy it
move.l d0,-(sp) ; copy it to the new port
move.l bkPixPat(a4),-(sp)
_CopyPixPat
noBkPixPat
move.l RGBFgColor(a3),RGBFgColor(a4) ; copy RGB foreground and background colors
move.l RGBFgColor+4(a3),RGBFgColor+4(a4)
move.l RGBBkColor+2(a3),RGBBkColor+2(a4)
move.l pnLoc(a3),pnLoc(a4) ; copy pen characteristics
move.l pnSize(a3),pnSize(a4)
move pnMode(a3),pnMode(a4)
move.l pnPixPat(a3),d0 ; get old pen pixel pattern
beq noPnPixPat ; if it is NIL, don't copy it
move.l d0,-(sp) ; copy it to the new port
move.l pnPixPat(a4),-(sp)
_CopyPixPat
noPnPixPat
move.l fillPixPat(a3),d0 ; get old fill pixel pattern
beq noFillPixPat ; if it is NIL, don't copy it
move.l d0,-(sp) ; copy it to the new port
move.l fillPixPat(a4),-(sp)
_CopyPixPat
noFillPixPat
lea pnVis(a3),a0 ; copy all remaining fields, starting from pnVis
lea pnVis(a4),a1
moveq #((portRec-pnVis)/2)-1,d0 ; number of words to copy (0-based for dbra)
@0 move (a0)+,(a1)+ ; copy one word
dbra d0,@0 ; loop until all copied
;----------------------------------------------------------------------------
; Update new pixmap with fields from old pixmap
move.l ([portPixMap,a3]),a0 ; get pointer to old pixmap
move.l ([portPixMap,a4]),a1 ; get pointer to new pixmap
move packType(a0),packType(a1) ; copy interesting fields
move.l packSize(a0),packSize(a1)
move.l hRes(a0),hRes(a1)
move.l vRes(a0),vRes(a1)
;----------------------------------------------------------------------------
; Update new grafVars with fields from old grafVars
MOVE.L grafVars(A3),A0 ;get src port grafVars <21>
_HandToHand ;make copy of handle <21>
BNE reportError ;leave if memory error <21>
MOVE.L grafVars(A4),A1 ;get handle to dst port grafVars <21>
MOVE.L A0,grafVars(A4) ;save new grafVars in dst port <21>
MOVE.L (A0),A0 ;deref new grafVars handle <21>
MOVE.L A1,D0 ;save handle to old grafVars <21>
MOVE.L (A1),A1 ;deref handle to old grafVars <21>
MOVE.L attachDevice(A1),attachDevice(A0) ;copy attachDevice from old to new <21>
MOVE.W devOwned(A1),devOwned(A0) ;copy devOwned, useMFTemp from old to new <21>
MOVE.L D0,A0 ;get handle to old grafVars back <21>
_DisposHandle ;dispose dst port grafvars handle <21>
;----------------------------------------------------------------------------
; Update new grafProcs with old grafProcs
move.l grafProcs(a3),grafProcs(a4) ; copy grafProcs handle from old to new gworld
;----------------------------------------------------------------------------
; Update new gDevice with fields from old gDevice
move.l ([grafVars,a3]),a0 ; get pointer to old grafVars
move.l ([attachDevice,a0]),a0 ; get pointer to old attached device
move.l ([grafVars,a4]),a1 ; get pointer to new grafVars
move.l ([attachDevice,a1]),a1 ; get pointer to new attached device
move.l gdSearchProc(a0),gdSearchProc(a1) ; copy interesting fields
move.l gdCompProc(a0),gdCompProc(a1)
move.l gdRefCon(a0),gdRefCon(a1)
;----------------------------------------------------------------------------
; Update new gDevice's pixmap with fields from old gDevice's pixmap
move.l ([gdPMap,a0]),a0 ; get pointer to old attached device's pixmap
move.l ([gdPMap,a1]),a1 ; get pointer to new attached device's pixmap
move packType(a0),packType(a1) ; copy interesting fields
move.l packSize(a0),packSize(a1)
move.l hRes(a0),hRes(a1)
move.l vRes(a0),vRes(a1)
;----------------------------------------------------------------------------
; Update foreground and background color indices while being compatible
; with the Palette Manager if active.
; Save Foreground and Background colors from the old gworld
move.l a3,-(sp) ; push pointer to old offscreen gworld
clr.l -(sp) ; use attached device
_SetGWorld ; set current port and device to old world
; If Palette Manager is there, use SaveFore and SaveBack to get fg and bk colors
if UsePaletteMgr then
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_SaveFore ; get foreground color from Palette Manager
pea saveBackColor(a6) ; push address of saved background ColorSpec
_SaveBack ; get background color from Palette Manager
; If Palette Manager is not there, use GetForeColor and GetBackColor instead
else
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_GetForeColor ; get foreground color from port
pea saveBackColor(a6) ; push address of saved background ColorSpec
_GetBackColor ; get background color from port
endif
; And restore them to new gworld, using the Palette Manager
move.l a4,-(sp) ; push pointer to new offscreen gworld
clr.l -(sp) ; use attached device
_SetGWorld ; set current port and device to new world
; If Palette Manager is there, use RestoreFore and RestoreBack to restore fg and bk colors
if UsePaletteMgr then
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_RestoreFore ; set foreground color with Palette Manager call
pea saveBackColor(a6) ; push address of saved background ColorSpec
_RestoreBack ; set background color with Palette Manager call
; If Palette Manager is not there, use RGBForeColor and RGBBackColor instead
else
pea saveForeColor(a6) ; push address of saved foreground ColorSpec
_RGBForeColor ; set foreground color
pea saveBackColor(a6) ; push address of saved background ColorSpec
_RGBBackColor ; set background color
endif
;----------------------------------------------------------------------------
; If the pixels in the old world are purged, don't update them
tst.b purged(a6) ; are the old pixels purged?
bne noCopyBits ; yes, don't CopyBits
; If flags is not 0, find out how the pixels will be updated and call CopyBits to update them
move.l gDevFlags(a6),d0 ; if flags is 0,
beq noCopyBits ; just set state of new offscreen buffer and return
;----------------------------------------------------------------------------
; Lock the pixels of both gworlds
clr.b -(sp) ; leave room for Boolean result
move.l portPixMap(a3),-(sp) ; handle to old offscreen PixMap
_LockPixels ; lock the pixels down
move.b (sp)+,d0 ; ignore result (if we're here, it means pixels are not purged)
clr.b -(sp) ; leave room for Boolean result
move.l newGWorld(a6),a0 ; get pointer to new offscreen GWorld
move.l portPixMap(a0),-(sp) ; push handle to new offscreen PixMap
_LockPixels ; lock the pixels down
move.b (sp)+,d0 ; if pixels are purged already, quit now
beq purgedError ; report error and exit
; Set current graphics world to new GWorld
move.l newGWorld(a6),-(sp) ; push pointer to new GWorld
clr.l -(sp) ; NIL device
_SetGWorld ; set current GWorld for CopyBits
;----------------------------------------------------------------------------
; Save the clipRgn of the newGWorld and set it to newGWorld's portRect
; so that CopyBits copies the whole pixmap
clr.l -(sp) ; leave room for RgnHandle result
_NewRgn ; create a new region for saveClip
move.l (sp),saveClip(a6) ; remember region handle in saveClip
_GetClip ; get the current clipRgn in saveClip
move.l newGWorld(a6),a0 ; get pointer to new GWorld
pea portRect(a0) ; push address of portRect
_ClipRect ; set clipRgn to portRect
;----------------------------------------------------------------------------
; Call CopyBits to update the pixels. Compute srcRect and dstRect according
; to update mode (clipping or stretching)
move.l ([portPixMap,a3]),-(sp) ; srcBits = pointer to old pixmap
move.l newGWorld(a6),a1 ; get pointer to new offscreen port
move.l ([portPixMap,a1]),-(sp) ; dstBits = pointer to new pixmap
lea portRect(a3),a0 ; get address of old portRect
lea portRect(a1),a1 ; get address of new portRect
move.l gDevFlags(a6),d0 ; get the flags
btst.l #stretchPixBit,d0 ; is stretchPixBit set?
bne.s doCopyBits ; yes, use srcRect and dstRect with no clipping
; If clipPixBit is set, clip CopyBits to size of destination rectangle
doClipping
move.l topLeft(a0),clipSrcRect+topLeft(a6) ; topLeft coordinates remain the same
move.l topLeft(a1),clipDstRect+topLeft(a6)
; Compute smallest height of old and new rectangle
move bottom(a0),d0 ; compute old height
sub top(a0),d0
move bottom(a1),d1 ; compute new height
sub top(a1),d1
cmp d0,d1 ; which height is smaller?
blt.s @0 ; new height is smaller, keep in d1
move d0,d1 ; old height is smaller, keep in d1
@0
move top(a0),d0 ; compute old top + clipped height
add d1,d0
move d0,clipSrcRect+bottom(a6) ; store in clipSrcRect.bottom
move top(a1),d0 ; compute new top + clipped height
add d1,d0
move d0,clipDstRect+bottom(a6) ; store in clipDstRect.bottom
; Compute smallest width of old and new rectangle
move right(a0),d0 ; compute old width
sub left(a0),d0
move right(a1),d1 ; compute new width
sub left(a1),d1
cmp d0,d1 ; which width is smaller?
blt.s @1 ; new width is smaller, keep in d1
move d0,d1 ; old width is smaller, keep in d1
@1
move left(a0),d0 ; compute old left + clipped width
add d1,d0
move d0,clipSrcRect+right(a6) ; store in clipSrcRect.right
move left(a1),d0 ; compute new left + clipped width
add d1,d0
move d0,clipDstRect+right(a6) ; store in clipDstRect.right
lea clipSrcRect(a6),a0 ; srcRect = smallest of old portRect and new portRect
lea clipDstRect(a6),a1 ; dstRect = idem but in coordinate system of new port
doCopyBits
move.l a0,-(sp) ; srcRect = old portRect (clipped or unclipped)
move.l a1,-(sp) ; dstRect = new portRect
move mode(a6),-(sp) ; mode = srcCopy or dither
move.l #nil,-(sp) ; no mask
_CopyBits ; transfer the pixels
;----------------------------------------------------------------------------
; Restore the clipRgn of the newGWorld
move.l saveClip(a6),-(sp) ; push handle to saveClip
_SetClip ; restore clipRgn
move.l saveClip(a6),-(sp) ; push handle to saveClip
_DisposRgn ; get rid of clipRgn
;----------------------------------------------------------------------------
; Unlock the pixels of the new offscreen GWorld (don't care about the old one, we'll get rid of it)
move.l newGWorld(a6),a0 ; get pointer to new offscreen GWorld
move.l portPixMap(a0),-(sp) ; push handle to its pixmap
_UnlockPixels ; unlock the pixels
;----------------------------------------------------------------------------
; After CopyBits, dispose of the old offscreen graphics world
noCopyBits
move.l a3,-(sp) ; push handle to old GWorld for dispose
;---------------------------------------------------------------------------- <17May90 KON>
; If savePort is the old GWorld, set savePort to the new one
; If saveDevice is the old attached device, set saveDevice to the new attached device
move.l a3,a0 ; get old GWorld
move.l newGWorld(a6),a3 ; get pointer to new GWorld
cmpa.l savePort(a6),a0 ; compare with savePort
bne.s checkSaveDevice ; if not the same, go check the saveDevice
move.l a3,savePort(a6) ; savePort is old GWorld, replace with new GWorld
checkSaveDevice
move.l ([grafVars,a0]),a0 ; get pointer to old grafVars
move.l attachDevice(a0),a0 ; get handle to old attached device
cmp.l saveDevice(a6),a0 ; compare with saveDevice
bne.s saveDeviceOK ; if not the same, just restore the current GWorld
move.l ([grafVars,a3]),a0 ; if same, replace with new attachDevice
move.l attachDevice(a0),saveDevice(a6)
saveDeviceOK
_DisposeGWorld ; dispose of it
;----------------------------------------------------------------------------
; Set lock/purge state of new offscreen buffer to the same as old offscreen buffer
setState
move.l newGWorld(a6),a3 ; get pointer to new GWorld
; Get here if restoring state of old offscreen buffer after an error (old GWorldPtr is in a3)
setStateWithError
move.l portPixMap(a3),-(sp) ; push handle to its pixmap
move.l state(a6),-(sp) ; push lock/purge state
_SetPixelsState ; set the state
; Restore current graphics world
move.l savePort(a6),-(sp) ; push pointer to saved port
move.l saveDevice(a6),-(sp) ; push handle to saved device
_SetGWorld ; restore current environment
;----------------------------------------------------------------------------
; Return pointer to new GWorld in offscreenGWorld
; If got here after an error, a3 contains the old graphics world
move.l offscreenGWorld(a6),a0 ; get pointer to GWorldPtr variable
move.l a3,(a0) ; store pointer to new GWorld in offscreenGWorld variable
exit move #noErr,QDErr ; assume no error <21Jun89> JCM
move.l result(a6),d0 ; copy result to d0 <21Jun89> JCM
bpl.s @0 ; if result is < 0, <21Jun89> JCM
move d0,QDErr ; copy low-word of result to QDErr <21Jun89> JCM
@0 ; <21Jun89> JCM
move.l saveStack(a6),sp ; restore the stack pointer
movem.l (sp)+,a2-a4/d5-d7 ; restore regs
unlk a6 ; get rid of stack frame
rtd #paramSize ; get rid of parameters and return to caller
;----------------------------------------------------------------------------
; Errors
reportError
ext.l d0 ; convert error to a long
move.l d0,result(a6) ; report error
bra.s setStateWithError ; restore state of old offscreen buffer and quit
badPixelDepth
move.l #cDepthErr,result(a6) ; pixel depth invalid
bra.s exit ; exit
getCTabError
move QDErr,d0 ; look at QDErr
bne reportError ; if contains an error, report it
move MemErr,d0 ; if no QDErr, look at MemErr
bne.s reportError ; if contains an error, report it
clr -(sp) ; if no MemErr, look at ResError
_ResError ; get Resource Manager error
move (sp)+,d0 ; look at it
bra.s setStateWithError ; restore state of old offscreen buffer and quit
; if no error anywhere, just return a cNoMemErr
purgedError
move.l #cNoMemErr,result(a6) ; report a Quickdraw memory error
bra.s setStateWithError ; restore state of old offscreen buffer and quit
paramError
move.l #paramErr,result(a6) ; report a parameter error
bra.s exit ; and exit
makeITabError
ext.l d0 ; convert QD error to long
move.l d0,result(a6) ; return QD error
move.l newCTable(a6),a0 ; get rid of color table and inverse table
_DisposHandle
move.l newITable(a6),a0
_DisposHandle
bra.s setStateWithError ; restore state of old offscreen buffer and quit
; If NewGWorld error fails and the old offscreen buffer was disposed of,
; reallocate old offscreen buffer, report error, and quit.
newGWorldError
move.l oldBufSize(a6),d1 ; get size of old offscreen buffer
beq.s reportError ; if 0, it means old offscreen hasn't been disposed of
move d0,d7 ; save error code
move.l d1,d0 ; get size of old offscreen buffer in d0
move.l ([grafVars,a3]),a0 ; get grafVars <07Jul89> JCM
tst.b useMFTemp(a0) ; were the pixels in temp memory? <07Jul89> JCM
beq.s @useCurHeap ; no, allocate in current heap <07Jul89> JCM
_NewTempHandle ; allocate it in Juggler heap, returns actual size in D0 <07Jul89> JCM
tst.l d0 ; is it empty? <07Jul89> JCM
bne.s @gotMem ; no, got the memory <07Jul89> JCM
move d7,d0 ; yes, restore error and report <07Jul89> JCM
bra reportError ; <07Jul89> JCM
@useCurHeap
_NewHandle ; allocate offscreen buffer (don't initialize it) <07Jul89> JCM
bne reportError ; if Memory Manager error, report it and quit <07Jul89> JCM
@gotMem
move.l ([portPixMap,a3]),a1 ; get pointer to old pixmap
move.l a0,baseAddr(a1) ; store handle to offscreen buffer in baseAddr
move d7,d0 ; restore error code
bra.s reportError ; report error and quit
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to OffscreenVersion (selector 20 on QDExtDispatcher).
;
;=========================================================================================
;=========================================================================================
OffscreenVersion PROC EXPORT
;----------------------------------------------------------------------------
;
; FUNCTION OffscreenVersion (): LONGINT;
;
; Returns the version number of the current version of the Quickdraw extensions.
; The first version doesn't have OffscreenVersion implemented and will therefore
; return a paramErr.
OffscreenVersNum equ $130 ; version 1.3 of the quickdraw extensions
;----------------------------------------------------------------------------
;
; Stack offsets of parameters
;
paramSize equ 0 ; size of parameters
version equ paramSize+4 ; LONG, result
move.l #OffscreenVersNum,version(sp) ; return version number
rts
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to QDExtDispatcher. Add selectors 22 and 23.
;
;=========================================================================================
;=========================================================================================
QDExtDispatcher PROC EXPORT
IMPORT Pixmap32Bit, GetGWorldPixMap, UpdateGWorld
ROMexit EQU $3FAC2
ROMDispatch EQU $3FA66
;----------------------------------------------------------------------------
; QDExtensions Dispatcher.
;
; All Quickdraw extensions routines use a common trap and a selector.
; The selector is in the low word of D0
; The size of the parameters is in the high word of D0
; NOTE: To avoid changing the include files again, functions number 0 through 19
; are accepted with an unspecified parameter size (high word of D0 cleared).
; In future versions, any new function should specify the size of parameters.
;----------------------------------------------------------------------------
cmp #23,d0 ; if unsigned d0 > max selector,
bhi.s exit ; don't do anything
cmp #3,d0
beq UpdateGWorld ;UpdateGWorld patched out above
cmp #20,d0 ;OffscreenVersion selector
beq.s OffscreenVersion ;OffscreenVersion patched out above
tst.w d0 ;selector 0 is NewGWorld
beq PatchNewGWorld
cmp #21,d0
ble.s GoROMDispatch ;Handle 0 - 21 with ROM
;
; Handle selectors 22 and 23 here
;
sub.w #22,d0 ;22 is 0th entry, 23 is 1st entry
jmp dispatchTable(d0*4) ; jump in jump table
dispatchTable
jmp Pixmap32Bit ; selector 22
jmp GetGWorldPixMap ; selector 23
GoROMDispatch
jmpROM ROMDispatch
exit
jmpROM ROMexit
Pixmap32Bit PROC EXPORT
;----------------------------------------------------------------------------
;
; FUNCTION Pixmap32Bit (pm: PixMapHandle): boolean;
;
;
; If pmVersion is PixMapVers4, the baseAddr is a 32-bit pointer, return true.
; If pmVersion is PixMapVers2, the baseAddr is a handle, return false.
; If pmVersion is PixMapVers1, the baseAddr is a 24-bit pointer, return false.
; If pmVersion is PixMapVers0,
; if the baseAddr is the same as a devicelist screen, then return true (for now)
; else return false.
;----------------------------------------------------------------------------
;
; Stack offsets of parameters
;
paramSize equ 4 ; size of parameters
bufResult equ paramSize+4 ; boolean, result
pm equ bufResult-4 ; LONG, handle to pixmap
; Initialize result to false (assume pmVersion is not PixMapVers4 or a screen).
move.l ([pm,sp]),a1 ; get pointer to pixmap
clr.w bufResult(sp) ; assume return false
; Check PixMap's pmVersion.
move pmVersion(a1),d0 ; get pmVersion
beq.s chkForScreen ; go check to see if it's a screen
cmp.w #PixMapVers4,d0 ; is it explicitly 32-bit?
bne.s exit ; no, return false
retTrue move.b #1,bufResult(sp) ; return true
exit rtd #paramSize ; get rid of parameters and return to caller
chkForScreen
move.l baseAddr(a1),d0 ; get baseAddr
MOVE.L DEVICELIST,A1 ; GET FIRST ELEMENT IN DEVICE LIST
NEXTGD MOVE.L (A1),A0 ; POINT TO DEVICE
MOVE.W GDFlags(A0),D2 ; get the flags word <5+>
MOVE.L GDPMAP(A0),A0 ; GET PIXMAP
MOVE.L (A0),A0 ; POINT TO PIXMAP
cmp.l baseAddr(A0),D0 ; compare base address
BNE.S @NxtDev ; doesn't match, so try next device <5+>
BTST #ext32Device,D2 ; is this a 32-bit accessed device? <5+>
BNE.s retTrue ; if so, then base addr 32-bit, ret true <5+>
BRA.S exit ; if not, then base addr 24-bit, ret false <5+>
@NxtDev
MOVE.L (A1),A0 ; GET DEVICE
MOVE.L GDNEXTGD(A0),D1 ; GET NEXT DEVICE
MOVE.L D1,A1 ; SAVE IT
BNE.S NEXTGD ;
bra.s exit ; not a screen so return false
ENDPROC
GetGWorldPixmap PROC EXPORT
;-----------------------------------------------------------
;
; FUNCTION GetGWorldPixmap (gw: GWorldPtr): pixmaphandle;
;
; Slimed from local routine PORTTOMAP found in colorasm.a
;
;
; Enter with: (sp): address of caller
; 4(sp): GworldPtr
; 8(sp): pixmap handle result
;
move.l (sp)+,a1 ;save caller's address
move.l (sp)+,a0 ;pick up GWorld (port) ptr
clr.l (sp) ;init result assuming failure
TST PORTBITS+ROWBYTES(A0) ;BITMAP OR PIXMAP?
BPL.S GOTBITMAP ;=>JUST A BITMAP
BTST #ISCPORT,PORTBITS+ROWBYTES(A0) ;IS IT A COLOR PORT?
BEQ.S GOTBITMAP ;=>NO, JUST A PIXMAP
MOVE.L portBits+BASEADDR(A0),(sp) ;ELSE GET PORT'S PIXMAP HANDLE
GOTBITMAP jmp (a1) ;return to caller
ENDPROC
MakeScaleTbl PROC EXPORT
MACRO
_ColorThing2Index
JSR ([$E00+$392*4])
ENDM
;---------------------------------------------------------------
;
; PROCEDURE MakeScaleTbl (PMP: PixMapPtr);
;
; Allocates a translate table on the stack and returns with SP at the
; start of the table. The translate table contains one entry for each
; possible pixel value in the source pixMap (PMP); each entry contains the
; value to be written to the destination pixMap to best approximate that color.
; The translation table has 32 bits per entry. <BAL 09May88> @@@@
;
redHigh EQU 8
greenHigh EQU 4
blueHigh EQU 0
&CurFile SETC 'STRETCH'
INCLUDE 'DrawingVars.a'
ScaleColorBit EQU 3
SwapFGBGBit EQU 4
UseStretchBit EQU 5
InvertItBit EQU 7
ColorizeInModeCaseBit EQU 8
ColorizeInSrcBufBit EQU 9
ciROMScaleBlt EQU $39f52
MOVE.L (SP)+,A0 ; get return address
MOVE.w (SP)+,D2 ; should we do colorizing here flag in bit 5
;
; <8JUN92 SAH>
; The old MakeScaleTbl used to use bit 5 for colorizing. It now uses bit 3 (ScaleColorBit).
; This didn't seem to cause many problems except now that ScaleBlt is being called
; again, we have problems when colorizing. So, rather than patch all of ScaleBlt for
; ci roms, we're doing a come from patch here. We can then then look at the actual XLateFlags
; from stretch (which is what should be passed to MakeScaleTbl anyway).
;
leaROM ciROMScaleBlt,a1 ;get where we want to check <8JUN92 SAH>
cmp.l a1,a0 ;is this from ScaleBlt? <8JUN92 SAH>
bne.s @colorizeOK ;no, so continue on <8JUN92 SAH>
move.w XLateFlag(a6),d2 ;get the real XLateFlags <9JUN92 SAH>
@colorizeOK
MOVE.L (SP)+,A1 ; get pixMap handle
MOVE pixelSize(A1),D1 ; get size of pixels
MOVEQ #1,D0 ; # entries = 2^pixelsize
LSL D1,D0 ; # entries = 2^pixelsize
MOVE D0,D1 ; save possible # of colors
SUBQ #1,D0 ; make zero based for DBRA
NXTWORD
move.l #$7fffffff,-(SP) ; allocate one entry per long <BAL 09May88> @@@@
DBRA D0,NXTWORD
; leave table on stack, save work regs, etc., on top of it
TBLOFST EQU 9*4+12 ; ret addr, save regs, RGBSpec, Back and ForeColor
MOVE.L A0,-(SP) ; push return address
MOVEM.L A2/D3-D7,-(SP) ; save work registers
MOVEQ #0,D5 ; clear high word
MOVE D1,D5 ; save # of available colors
SUBQ #6,SP ; allocate VAR ColorSpec on stack
clr.w -(sp) ; force default color space to RGB <BAL/dvb 23Feb89>
;
; Allocate forecolor and back color on stack for colorizing and for use later
;
move.l a1,a2 ;save pixmap handle
MOVEQ #-1,D0 ;GET WHITE
MOVE.L D0,-(SP) ;PUSH R,G,B FOR WHITE
MOVE D0,-(SP)
CLR.L -(SP) ;PUSH R,G,B FOR BLACK
CLR -(SP)
btst #ScaleColorBit,d2 ;should we colorize?
beq @useDefault ;skip if no.
moveq #6,d4
btst #swapfgbgBit,d2 ;swap fg/bk colors?
beq.s @dontswap
moveq #0,d4
@dontswap
PEA (SP,d4)
_GetBackColor ;get fg, bg to do colorizing
eor.w #6,d4
PEA (sp,d4)
_GetForeColor
;
; Check to see if destination device is 1 bit deep. If so, we need to see if the fg and bg
; colors map to the same thing. If they do, then check to see if the colors themselves are
; the same. If not, then we invert the bg color <08JUN92 SAH>
;
; <135> <18AUG92 SAH>
; NOTE: This check is not correct. It should check to see if the destination is 1 or 2
; bits deep and is a new port. There is also a major bug where we colorize with the inverted
; background color rather than just setting the background index. In particular, this breaks
; SeedCFill for indexed pixmaps. For the purposes of Cube-E, we will do an explicit check to
; see if the background color is white and the foreground is black, if so we won't invert.
;
move.l ([theGDevice]),A0 ;get a pointer to the device
move.l ([gdPMap,a0]),a0 ;get a pointer to its pixmap
cmp.w #1,pixelSize(a0)
bne.s @fgBgColorsOK ;not one bit, we don't have to worry
move.w d2,d3 ;save d2 here from _Color2Index <09JUN92 SAH>
; now do the check for fg = black, bg = white <18AUG92 SAH>
tst.l (sp) ;look at fg red and green <135>
bne.s @doInvertCheck ;not black, so bail <135>
tst.w 4(sp) ;look at fg blue <135>
bne.s @doInvertCheck ;not black, so bail <135>
moveq #-1,d0 ;get a white long <135>
cmp.l 6(sp),d0 ;compare with bg red and green <135>
bne.s @doInvertCheck ;not white, so bail <135>
cmp.w 10(sp),d0 ;compare with bg blue <135>
beq.s @fgBgColorsOK ;equal, so don't do invert <135>
@doInvertCheck
; get copies of our colors on the stack <09JUN92 SAH>
; it starts out like this. Make sure we copy things in the right order!
; RRRRGGGG 0
; BBBBrrrr 4
; ggggbbbb 8
move.l 8(sp),-(sp) ;do ggggbbbb
move.l 8(sp),-(sp) ;do BBBBrrrr
move.l 8(sp),-(sp) ;do RRRRGGGG
;now we have another copy of the above
subq.l #4,sp ;room for index
pea 4(sp) ;ptr to the bg color
_Color2Index
subq.l #4,sp ;room for index
pea 14(sp) ;ptr to the fg color
_Color2Index
move.w d3,d2 ;get our d2 back from _Color2Index <09JUN92 SAH>
move.l (sp)+,d0 ;get the fg color
cmp.l (sp)+,d0 ;compare against the bg color
add.w #12,sp ;get rid of our private colors
bne.s @fgBgColorsOK ;we're ok
;now, the two map to the same thing, so we need to check of the colors themselves
;are the same. If so, we don't do anything.
move.l 0(sp),d0
cmp.l 6(sp),d0
bne.s @invertbg
move.w 4(sp),d0
cmp.w 10(sp),d0
beq.s @fgBgColorsOK
@invertbg
pea 6(sp) ;push ptr to bg color
_InvertColor ;and invert it
@fgBgColorsOK
;
; if foreground black and background white, don't colorize.
;
move.l 0(sp),d4 ;get long of fg color
bne.s @useDefault ;abort if not black
move.w 4(sp),d4 ;get high word of fg color
bne.s @useDefault ;abort if not black
;
; check fg color
;
move.l 6(sp),d4 ;get long of bg color
addq #1,d4 ;check for white
bne.s @useDefault
move.w $0A(sp),d4 ;check high word
add.w #1,d4
bne.s @useDefault
bclr #ScaleColorBit,d2 ;fg black, bk white, don't colorize
@useDefault
;
; Build pixel translation table
;
move.l a2,a1 ;get pm handle back
MOVEQ #-1,D6 ; assume no colors in color table
MOVE.L pmTable(A1),D0 ; does it exist?
BEQ noPredefinedColors
MOVE.L D0,A2 ; get color table handle
MOVE ([A2],CTSize),D4 ; get size of table in entries
cmp D5,D4 ; more entries than bits allow?
blo.s @notTooMany ; no, fine
move D5,D4 ; yes, pin to depth
subq #1,D4 ; make zero-based
@notTooMany
MOVE ([a2],TransIndex),D3 ; get ctFlags <BAL 10Mar89>
btst #14,d3 ; are they palette references? <BAL 10Mar89>
bne brink ; yes call dave <BAL 10Mar89>
MOVEQ #0,D6 ; zero high word
MOVE D4,D6 ; remember number of colors
btst #ScaleColorBit,d2 ;should we colorize?
beq.s noColorizeLoop ;skip if no.
@nxtEntry MOVE.L (A2),A0 ; get color table pointer
MOVE D4,D3 ; assume entry = index
TST TransIndex(A0) ; look for flag in transIndex
BMI.S @UseIndex ; => flag set, use index
MOVE.w CTTable+value(A0,D4*8),D3 ; get value of current entry <BAL/dvb 23Feb89>
@UseIndex MOVE CTTable+rgb+red(A0,D4*8),d0 ; get red
;
; colorize the red
;
MOVE.w D0,d1 ;COPY SRC
move.w 6(sp),d2 ;get red of bk color into low 16 bits
AND.w D2,D0 ;ADD FG COLOR TO SRC
NOT.w D1 ;GET NOT SRC
move 0(sp),d2 ;get red of fg color into low 16 bits
AND.w D2,D1 ;ADD BK COLOR TO NOT SRC
OR.w D1,D0 ;COMBINE FG/BK DATA
move.w d0,rgb+red+12(sp)
MOVE.L CTTable+rgb+green(A0,D4*8),d0 ; copy green,blue
;
; colorize the green and blue at the same time
;
MOVE.l D0,d1 ;COPY SRC
move.l 8(sp),d2 ;get blue and green of bk color
AND.l D2,D0 ;ADD FG COLOR TO SRC
NOT.l D1 ;GET NOT SRC
move.l 2(sp),d2 ;get blue and green of fg color
AND.l D2,D1 ;ADD BK COLOR TO NOT SRC
OR.l D1,D0 ;COMBINE FG/BK DATA
move.l d0,rgb+green+12(SP)
CLR.L -(SP) ; make room for function result
PEA rgb+4+12(SP) ; point to VAR RGBColor <KON 28Apr90>
_Color2Index ; convert to index <BAL/dvb 23Feb89>
MOVE.L (SP)+,D0 ; get result
move.l D0,TBLOFST(SP,D3*4) ; put returned value in table <BAL 09May88> @@@@
DBRA D4,@nxtEntry ; => repeat until done
bra.s noPredefinedColors
noColorizeLoop
@nxtEntry MOVE.L (A2),A0 ; get color table pointer
MOVE D4,D3 ; assume entry = index
TST TransIndex(A0) ; look for flag in transIndex
BMI.S @UseIndex ; => flag set, use index
MOVE.w CTTable+value(A0,D4*8),D3 ; get value of current entry <BAL/dvb 23Feb89>
@UseIndex MOVE CTTable+rgb+red(A0,D4*8),rgb+red+12(sp)
MOVE.L CTTable+rgb+green(A0,D4*8),rgb+green+12(SP)
CLR.L -(SP) ; make room for function result
PEA rgb+4+12(SP) ; point to VAR RGBColor <KON 28Apr90>
_Color2Index ; convert to index <BAL/dvb 23Feb89>
MOVE.L (SP)+,D0 ; get result
move.l D0,TBLOFST(SP,D3*4) ; put returned value in table <BAL 09May88> @@@@
DBRA D4,@nxtEntry ; => repeat until done
bra.s noPredefinedColors
brink MOVEQ #0,D6 ; zero high word
MOVE D4,D6 ; remember number of colors
@nxtPEntry MOVE.L (a2),A0 ; get color table pointer
MOVE D4,D3 ; assume entry = index
MOVE.w CTTable+value(A0,D4*8),12(sp) ; put pmIndex in colorSpec <KON 28Apr90
MOVE CTTable+rgb+red(A0,D4*8),rgb+red+12(SP) ; copy value, red <KON 28Apr90
MOVE.L CTTable+rgb+green(A0,D4*8),rgb+green+12(SP) ; copy green,blue <KON 28Apr90
CLR.L -(SP) ; make room for function result
PEA 4+12(SP) ; point to VAR ColorSpec <KON 28Apr90
_ColorThing2Index ; convert to index <BAL/dvb 23Feb89>
MOVE.L (SP)+,D0 ; get result
move.l D0,TBLOFST(SP,D3*4) ; put returned value in table <BAL 09May88> @@@@
DBRA D4,@nxtPEntry ; => repeat until done
clr.w QDErr ;remove any lingering error from ColorThing2Index
; <BAL 28Jan90>
; leave ColorSpec on stack
noPredefinedColors
; figure the number of unused colors
ADDQ.L #1,D6 ; make the number of colors 1 based
SUB.L D5,D6 ; figure difference between bit depth and colors defined
NEG.L D6 ; figure number of unused colors (zero based)
bgt.s @continue
; if negative or zero, strip foreground and background colors off stack: all done
add #12,sp ;throw away fore and back colors
bra @noRelativeColors
;
; At this point forecolor is on top of stack
;
@continue
MOVE.L SP,A1
MOVE.L A1,A2 ; save a copy of where the foreground is
MOVEQ #2,D0 ; three colors, two based
@startColor
MOVE #$8000,-(SP) ; put 1/2 on stack
MOVE (A1)+,-(SP) ; save integer on stack
DBRA D0,@startColor
MOVE.L A2,A1 ; start back with forecolor
LEA TBLOFST+12(SP,D5*4),A2 ; start of stack based table + 2 (12 bytes long colors) <KON 6MAR91>
SUBQ #1,D6 ; number of new colors, zero based
BEQ.S @skipDivision ; if only 1 color left, no need to interpolate
LEA 6(A1),A0 ; get start of real background color
MOVEQ #2,D0 ; three colors, one based
@nextColor
MOVEQ #0,D1 ; clear high word
MOVE (A0)+,D1 ; background color component
SUB (A1)+,D1 ; change from foreground
SLO D7 ; remember if it was negated
BHS.S @orderedOK
NEG D1 ; flip if subtraction would overflow
@orderedOK
SWAP D1 ; multiply high word times 65K
DIVU.L D6,D1 ; figure fixed point color increment
TST.B D7
BEQ.S @notFlipped
NEG.L D1 ; flip it
@notFlipped
MOVE.L D1,-(SP) ; save it
DBRA D0,@nextColor
MOVEM.L (SP)+,D3-D5 ; load red, blue, green increments into registers
@skipDivision
@findUnused
cmp.l #$7fffffff,-(A2) ; is it unused? <HACK> <BAL 09May88> @@@@
bne.s @findUnused ; if not, plow onward <BAL 09May88> @@@@
MOVE redHigh(SP),red+12(SP) ; >> redHigh = 8
MOVE greenHigh(SP),green+12(SP) ; >> greenHigh = 4
MOVE blueHigh(SP),blue+12(SP) ; >> blueHigh = 0
CLR.L -(SP) ; make room for function result
PEA 16(SP) ; location of RGBColor
_Color2Index
MOVE.L (SP)+,D0 ; get long result
move.l D0,(A2) ; save away index <BAL 09May88> @@@@
MOVEM.L (SP)+,D0-D2 ; last colors
ADD.L D3,D0
ADD.L D4,D1
ADD.L D5,D2 ; increment red, blue green
MOVEM.L D0-D2,-(SP) ; save them for next time
DBRA D6,@findUnused
ADD #24,SP ; throw away 3 long colors
@noRelativeColors
MOVEM.L (SP)+,A2/D0-D1/D3-D7 ; toss 8 on stack (D0,D1) & restore work registers
RTS
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to GetCIcon. When calculating icon size, don't multiply by
; pixelSize since rowBytes already includes the depth.
;
;=========================================================================================
;=========================================================================================
GETCICON PROC EXPORT
ciGetCIcon EQU $3126A
ciNoGetNew EQU $3128A
;-------------------------------------------------------------
;
; FUNCTION GetCIcon(cIconID: INTEGER): cIconHandle;
;
; See description in Patterns.a
;
PARAMSIZE EQU 2
result EQU PARAMSIZE+8 ; cIconHandle RESULT
cIconID EQU PARAMSIZE+8-2 ; icon ID
LINK A6,#0 ; build stack frame
MOVEM.L D3-D4/A2-A4,-(SP) ; preserve work registers
CLR.L RESULT(A6) ; set result to NIL
; Load the data, detach from resource manager and lock it down
SUBQ #4,SP ; make space for result
MOVE.L #'cicn',-(SP) ; push resource type
MOVE cIconID(A6),-(SP) ; push resource ID
_GetResource ; get the resource
MOVE.L (SP)+,A0 ; keep handle in A0 <1.5> BAL
MOVE.L A0,D0 ; did we get one? <1.5> BAL
BEQ NoGetNew ; if not, don't allocate one
; copy resource data to the main pattern/cursor data structure, keep in A4
; The resource should be purgeable. Just leave it lying around.
_HandToHand ; create a copy without purgeing src <1.5> BAL
move.l A0,A4 ; get new handle into A4 <1.5> BAL
_HLock ; and lock it down
; Point to the color table
MOVE.L (A4),A3 ; keep pointer in A3
MOVE iconPMap+bounds+bottom(A3),D4 ; get bottom
SUB iconPMap+bounds+top(A3),D4 ; calc height, keep in D4
LEA iconRec(A3),A2 ; point to the mask data
MOVE iconMask+rowbytes(A3),D0 ; get mask's rowbytes
MULU D4,D0 ; get size of mask data
ADD D0,A2 ; point to bitmap table
MOVE iconBMap+rowbytes(A3),D0 ; get bitMap's rowbytes
MULU D4,D0 ; get size of bitmap data
ADD D0,A2 ; point to color table
; Install the color table
CLR.L -(SP) ; make room for function result
_GetCTSeed ; go get seed for new color table
MOVE.L (SP)+,CTSeed(A2) ; and set seed value
MOVE.L A2,A0 ; point to the color table data
MOVE CTSize(A2),D0 ; get number of entries in table
ADDQ #1,D0 ; make it one based
MULU #CTEntrySize,D0 ; get size of entries
ADD #CTRec,D0 ; add in size of header
EXT.L D0 ; long for PtrToHand
MOVE.L D0,D3 ; save size in D4
_PtrToHand ; get a new handle into A0
BNE NoGetNew ; =>exit if no memory
MOVE.L A0,iconPMap+pmTable(A3) ; install color table into pixMap
; Create the pixMap's data handle and install it
MOVE.L A2,A0 ; point to the color table
ADD.L D3,A0 ; bump to beginning of pixel data
MOVE iconPMap+rowBytes(A3),D0 ; get the pixMap rowbytes
AND #nuRBMask,D0 ; clear flag bits
MULU D4,D0 ; multiply rowbytes * height
; MULU iconPMap+pixelSize(A3),D0 ; and multiply by depth for size (silly mistake!!)
jmpROM ciGetCIcon
NoGetNew jmpROM ciNoGetNew
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to StdOpcodeProc. This patch takes care of adjusting the picframe when hres and
; vres information is supplied in the header.
;
;=========================================================================================
;=========================================================================================
StdOpcodeProc PROC EXPORT
; IMPORT GetLong,GetPicdata
ciGetLong EQU $32B90
ciGetPicdata EQU $32BA0
;--------------------------------------------
;
; OFFSETS WITHIN A PICTURE PLAY STATE RECORD:
;
THERECT EQU 0 ;RECT
PENLOC EQU THERECT+8 ;POINT
TEXTLOC EQU PENLOC+4 ;POINT
OVALSIZES EQU TEXTLOC+4 ;POINT
FROMRECT EQU OVALSIZES+4 ;RECT
TORECT EQU FROMRECT+8 ;RECT
NUMER EQU TORECT+8 ;POINT
DENOM EQU NUMER+4 ;POINT
THECLIP EQU DENOM+4 ;RGNHANDLE
USERCLIP EQU THECLIP+4 ;RGNHANDLE
PLAYVERSION EQU USERCLIP+4 ;PICTURE VERSION
TXHFRAC EQU PLAYVERSION+2 ;FRACTIONAL TEXT POSITION
NEWHFRAC EQU TXHFRAC+2 ;UPDATED FRACTION RECIEVED
TEMPPIXPAT EQU NEWHFRAC+2 ;PIXPAT FOR PLAYING NEW PICS IN OLD PORTS
FontMappingTbl EQU TEMPPIXPAT+4 ;Handle to array of old,new font id pairs
PSreserve1 EQU FontMappingTbl+4 ;reserved
PSreserve2 EQU PSreserve1+4 ;reserved
PLAYREC EQU PSreserve2+4 ;TOTAL SIZE
;------------------------------------------------------
;
; New offsets in a PICT2 header record:
;
hdrVersion EQU 0 ;Word (=-2)
hdrReserved EQU hdrVersion+2 ;Word
hdrHRes EQU hdrReserved+2 ;Fixed
hdrVRes EQU hdrHRes+4 ;Fixed
hdrSrcRect EQU hdrVRes+4 ;Rect
hdrReserved2 EQU hdrSrcRect+8 ;Long
picHdrSize EQU hdrReserved2+4 ;size of a PICT2 header record
;------------------------------------------------------------------
;
; PROCEDURE StdOpcode(fromRect,toRect: Rect; opcode,version: INTEGER);
;
; GETS CALLED FOR OPCODE VALUES $0100-$FFFF
;
; OPCODE: $0100-$01FF 2 BYTES DATA
; $0200-$02FF 4 BYTES DATA
; ...
; $7F00-$7FFF 254 BYTES DATA
; $8000-$80FF 0 BYTES DATA
; $8100-$FFFF 4 BYTES SIZE + SIZE BYTES DATA
;
; THIS PROCEDURE READS THE OPCODE'S DATA AND IGNORES IT
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 12
pFROMRECT EQU PARAMSIZE+8-4 ;LONG
pTORECT EQU pFROMRECT-4 ;LONG
OPCODE EQU pTORECT-2 ;WORD
VERSION EQU OPCODE-2 ;WORD
LINK A6,#0 ;NO LOCAL VARS
MOVEM.L D6/D7,-(SP) ;SAVE WORK REGISTERS
MOVE.L #256,D6 ;GET USEFUL NUMBER
SUB.L D6,SP ;ALLOCATE STACK BUFFER
MOVE OPCODE(A6),D0 ;GET THE OPCODE
BMI.S GETSIZE ;=>OP CONTAINS SIZE
LSR #8,D0 ;GET SIZE/2 IN LOW NIBBLE
ADD D0,D0 ;CALC SIZE
EXT.L D0 ;MAKE IT LONG
BRA.S SHARE ;=>USE COMMON CODE
GETSIZE AND #$7F00,D0 ;MASK THE OPCODE
BEQ.S DONE ;=>NO DATA BYTES
jsrROM ciGetLong ;READ IN SIZE
SHARE MOVE.L D0,D7 ;SAVE WHOLE SIZE
NXTCHNK MOVE D6,D0 ;ASSUME SIZE >= 256
CMP.L D6,D7 ;IS SIZE >= 256?
BGE.S SIZEOK ;=>YES, SKIP 256 BYTES
MOVE D7,D0 ;ELSE SKIP REMAINING BYTES
SIZEOK MOVE.L SP,-(SP) ;PUSH BUFFER POINTER
MOVE D0,-(SP) ;PUSH BYTECOUNT
if TheFuture then ; <124> Take out of current builds
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <121>
beq.s Done
endif ; <124>
jsrROM ciGetPicdata ;READ DATA INTO BUFFER
SUB.L D6,D7 ;SUBTRACT BUFSIZE FROM COUNT
BGT.S NXTCHNK ;=>GO SKIP NEXT CHUNK
;Slimey hack assumes that StdOpCodeProc is called with a pointer to the fromRect inside
;the active playstate record for the pict. Fortunately, this is the case. Otherwise, the
;"illegal" altering of Denom and FromRect would not affect the picture playback.
;If this opcode were in the midst of a picture (or we supported more than one per pict)
;then we would also have to remap the pensize and potentially the cliprgn as well.
cmp.w #ngHeaderOp,OPCODE(a6) ;pict2 header opcode?
bne.s done ;not a pict2 header opcode
cmp.w #$fffe,(sp) ;is it version -2 header?
bne.s done ;<27nov89 KON>
move.l pFromRect(a6),a1 ;point to playstate's FromRect
lea hdrSrcRect(sp),a0 ;point to sourceRect stored in header record
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0 ;CALC SRC WIDTH
MOVE D0,DENOM+H-FromRect(A1) ;DENOM.H := SRC WIDTH
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0 ;CALC SRC HEIGHT
MOVE D0,DENOM+V-FromRect(A1) ;DENOM.V := SRC HEIGHT
MOVE.L (A0)+,(A1)+
MOVE.L (A0)+,(A1)+ ;FROMRECT := PICFRAME
DONE ADD.L D6,SP ;STRIP BUFFER
MOVEM.L (SP)+,D6/D7 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'STDPICPR'
ENDPROC
;=========================================================================================
;=========================================================================================
;
; Patch to DrawPicture. This patch performs font name/ID binding on picture playback
; We need the entire routine since the stack frame has changed from the ROM version.
; Specifically, SAVEPORT moved and is used near the end of this routine.
;
; Patch to DrawPicture. This patch also handles the line-layout state on picture
; playback for the Script Manager.
;
;=========================================================================================
;=========================================================================================
DrawPicture PROC EXPORT
; IMPORT PicItem1,NewRgn,InitColorStuff
;------------------------------------------------------------------
;
; PROCEDURE DrawPicture(myPicture: PicHandle; dstRect: Rect);
;
;
; -- ROM Entry points
;
InitColorStuff EQU $30160
;--------------------------------------------
;
; OFFSETS WITHIN A PICTURE PLAY STATE RECORD:
;
THERECT EQU 0 ;RECT
PENLOC EQU THERECT+8 ;POINT
TEXTLOC EQU PENLOC+4 ;POINT
OVALSIZES EQU TEXTLOC+4 ;POINT
FROMRECT EQU OVALSIZES+4 ;RECT
TORECT EQU FROMRECT+8 ;RECT
NUMER EQU TORECT+8 ;POINT
DENOM EQU NUMER+4 ;POINT
THECLIP EQU DENOM+4 ;RGNHANDLE
USERCLIP EQU THECLIP+4 ;RGNHANDLE
PLAYVERSION EQU USERCLIP+4 ;PICTURE VERSION
TXHFRAC EQU PLAYVERSION+2 ;FRACTIONAL TEXT POSITION
NEWHFRAC EQU TXHFRAC+2 ;UPDATED FRACTION RECIEVED
TEMPPIXPAT EQU NEWHFRAC+2 ;PIXPAT FOR PLAYING NEW PICS IN OLD PORTS
FontMappingTbl EQU TEMPPIXPAT+4 ;Handle to array of old,new font id pairs
PSreserve1 EQU FontMappingTbl+4 ;reserved
PSreserve2 EQU PSreserve1+4 ;reserved
PLAYREC EQU PSreserve2+4 ;TOTAL SIZE
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE EQU 8
MYPICTURE EQU PARAMSIZE+8-4 ;LONG, PICHANDLE
DSTRECT EQU MYPICTURE-4 ;LONG, ADDR OF RECT
PLAYSTATE EQU -PLAYREC ;PICTURE PLAY STATE RECORD
SAVEPORT EQU PLAYSTATE-PORTREC ;GRAFPORT RECORD
saveQdRunSlop equ SAVEPORT-4 ;Fixed <54>
saveQdChExtra equ saveQdRunSlop-4 ;Fixed <54>
saveOutline equ saveQdChExtra-1 ;Byte
savePreserve equ saveOutline-1 ;Byte
saveFractional equ savePreserve-1 ;Byte
saveUnscaled equ saveFractional-1 ;Byte
VARSIZE EQU saveUnscaled ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGISTERS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
TST.L MYPICTURE(A6) ;IS PICHANDLE NIL ?
BEQ GOHOME ;YES, QUIT
;--------------------------------------------------
;
; SET UP NUMER AND QUIT IF DSTRECT WIDTH OR HEIGHT IS <= 0
; COPY DSTRECT INTO TORECT
;
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0 ;CALC DST WIDTH
BLE GOHOME ;QUIT IF WIDTH <= 0
MOVE D0,PLAYSTATE+NUMER+H(A6) ;NUMER.H := DST WIDTH
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0 ;CALC DST HEIGHT
BLE GOHOME ;QUIT IF HEIGHT <= 0
MOVE D0,PLAYSTATE+NUMER+V(A6) ;NUMER.V := DST HEIGHT
LEA PLAYSTATE+TORECT(A6),A1
MOVE.L (A0)+,(A1)+
MOVE.L (A0)+,(A1)+ ;TORECT := DSTRECT
;--------------------------------------------------
;
; SET UP DENOM AND QUIT IF PICFRAME WIDTH OR HEIGHT IS <= 0
; COPY PICFRAME INTO FROMRECT.
;
MOVE.L MYPICTURE(A6),A0 ;GET PICHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
;if PICT 2 and header version = -2, use source rect instead of picFrame.
;<<<Moved to StdOpcodeProc to support spooling>>>
; cmp.l #$001102ff,picData(a0) ;PICT 2 ?
; bne.s @notPic2
; cmp.l #$0c00fffe,picData+4(a0) ;hdr version -2 ?
; bne.s @notPic2
; lea picData+4+2+hdrSrcRect(a0),a0 ;point to srcRect
; bra.s @share
@notPic2
LEA PICFRAME(A0),A0 ;POINT TO PICTURE FRAME
@share
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0 ;CALC SRC WIDTH
BLE GOHOME ;QUIT IF WIDTH <= 0
MOVE D0,PLAYSTATE+DENOM+H(A6) ;DENOM.H := SRC WIDTH
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0 ;CALC SRC HEIGHT
BLE GOHOME ;QUIT IF HEIGHT <= 0
MOVE D0,PLAYSTATE+DENOM+V(A6) ;DENOM.V := SRC HEIGHT
LEA PLAYSTATE+FROMRECT(A6),A1 ;POINT TO FROMRECT
MOVE.L (A0)+,(A1)+
MOVE.L (A0)+,(A1)+ ;FROMRECT := PICFRAME
;---------------------------------------------------
;
; PRESERVE THE CURRENT GRAFPORT IN SAVEPORT
;
MOVE.L A3,A0 ;SRC = THEPORT
LEA SAVEPORT(A6),A1 ;DST = SAVEPORT
MOVEQ #PORTREC/2-1,D0 ;INIT DBRA COUNT
SAVELP MOVE.W (A0)+,(A1)+ ;COPY A WORD
DBRA D0,SAVELP ;LOOP ENTIRE PORT
;---------------------------------------------------
;
; PRESERVE AND INIT THE CURRENT LINE-LAYOUT STATE
;
IF SCRIPT_CHAR_EXTRA THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals. <54>
move.l qdChExtra(a0),saveQdChExtra(a6) ; save character extra amount. <54>
move.l qdRunSlop(a0),saveQdRunSlop(a6) ; save run slop amount. <54>
clr.l qdChExtra(a0) ; clear character extra amount. <54>
clr.l qdRunSlop(a0) ; clear run slop amount. <54>
ENDIF
;---------------------------------------------------
;
; PRESERVE THE INITIAL GLYPH RENDERING STATE
;
IF hasGlyphState THEN
btst.b #splinePreferred,HiliteMode ; bit flag set in HiliteMode?
sne.b saveOutline(a6) ; yes, set outline preferred flag
btst.b #preserveGlyph,HiliteMode ; bit flag set in HiliteMode?
sne.b savePreserve(a6) ; yes, set preserve glyph flag
move.b FractEnable,saveFractional(a6) ; save fractional widths flag
move.b FScaleDisable,saveUnscaled(a6) ; save scale disable flag
ENDIF
;----------------------------------------
;
; INIT GLOBAL VARS:
;
CLR.L PATALIGN(A4) ;PATALIGN := (0,0)
MOVE.L MYPICTURE(A6),PLAYPIC(A4) ;SAVE PICTURE FOR STDGETPIC
MOVE.L #PICDATA,PLAYINDEX(A4) ;INIT INDEX TO FIRST OPCODE
;----------------------------------------
;
; INIT PLAY STATE RECORD:
;
LEA PLAYSTATE(A6),A0
CLR.L (A0)+ ;THERECT := (0,0,0,0)
CLR.L (A0)+
CLR.L (A0)+ ;PENLOC := (0,0)
CLR.L (A0)+ ;TEXTLOC := (0,0)
CLR.L (A0)+ ;OVALSIZES := (0,0)
;FROMRECT SET UP
;TORECT SET UP
;NUMER SET UP
;DENOM SET UP
MOVE.L CLIPRGN(A3),PLAYSTATE+USERCLIP(A6) ;SAVE USER CLIPRGN
CLR.L -(SP)
_NEWRGN
MOVE.L (SP)+,PLAYSTATE+THECLIP(A6) ;ALLOCATE THECLIP
MOVE #$8000,D0 ;INITIALIZE FRACTIONAL PARTS
MOVE D0,PLAYSTATE+TXHFRAC(A6) ;TXHFRAC = 1/2
MOVE D0,PLAYSTATE+NEWHFRAC(A6) ;NEW FRACTION = 1/2
;
; Allocate handle for mapping of fond id's we have seen so far
;
; Format of FontMappingTbl handle is:
; handle size [long]
; # of entries - 1 used [word]
; oldID1,newID1 ... oldIDn,newIDn
FontMapSize equ 25*4
doFontList
moveq #FontMapSize+6,d0 ;initial size for 50 entries
_NewHandle
move.l a0,PLAYSTATE+FontMappingTbl(a6) ;save picFontList handle in picSave record
beq.s @noHandle
move.l (a0),a0 ;point into fontList
moveq #FontMapSize+6,d0 ;initial size for 25 entries
move.l d0,(a0)+
move.w #-1,(a0) ; 0 entries
; clr.l (a0)+ ; 1 entry, first oldID = 0
; clr.w (a0) ; first newID = 0
@noHandle
;--------------------------------------------------------
;
; INIT MOST FIELDS OF THEPORT
;
CLR.L -(SP)
_NEWRGN
MOVE.L (SP)+,CLIPRGN(A3) ;ALLOCATE TEMP CLIPRGN
LEA BKPAT(A3),A0 ;POINT TO BKPAT
CLR.L (A0)+ ;BKPAT := WHITE
CLR.L (A0)+
MOVEQ #-1,D0 ;GET SOME BLACK
MOVE.L D0,(A0)+ ;fillPat := BLACK
MOVE.L D0,(A0)+
CLR.L (A0)+ ;PNLOC := (0,0)
MOVE.L #$00010001,D1
MOVE.L D1,(A0)+ ;pnSize := (1,1)
MOVE #8,(A0)+ ;pnMode := patCopy
MOVE.L D0,(A0)+ ;pnPat := black
MOVE.L D0,(A0)+
ADD #2,A0 ;skip over pnVis
CLR.L (A0)+ ;txFont, txFace := 0
MOVE #1,(A0)+ ;txMode := srcOr
CLR (A0)+ ;txSize := 0;
CLR.L (A0)+ ;spExtra := 0.0;
MOVE.L #blackColor,(A0)+ ;FGCOLOR := blackColor
MOVE.L #whiteColor,(A0)+ ;BKCOLOR := whiteColor
;LEAVE COLRBIT ALONE
;LEAVE PATSTRETCH ALONE
;LEAVE PICSAVE ALONE
;LEAVE RGNSAVE ALONE
;LEAVE POLYSAVE ALONE
;LEAVE GRAFPROCS ALONE
;--------------------------------------------------
;
PEA PNSIZE(A3) ;Scale initial pensize <BAL/CSD 02Apr89>
PEA FROMRECT+PLAYSTATE(A6) ;so that 1,1 lines scale
PEA TORECT+PLAYSTATE(A6)
_SCALEPT ;SCALE PNSIZE
;--------------------------------------------------
;
; IF IT'S A NEW GRAFPORT, SET UP NEW FIELDS IN GRAFPORT.
;
TST PORTBITS+ROWBYTES(A3) ;IS IT A NEW GRAFPORT?
BMI.S @NEWPIC ;=>YES, INSTALL NEW FIELDS
; IF OLD GRAFPORT, ALLOCATE A PIXPAT TO READ INTO
CLR.L -(SP) ;MAKE ROOM FOR FUNCTION RESULT
_NEWPIXPAT ;ALLOCATE A PIXPAT
MOVE.L (SP)+,PLAYSTATE+TEMPPIXPAT(A6) ;SAVE IN PLAYSTATE RECORD
BRA.S DRAWPIC ;AND SKIP NEW GRAFPORT STUFF
; INVALIDATE PIXPAT FIELDS SO THEY GET NEW PIXPATS INSTALLED
@NEWPIC CLR.L BKPIXPAT(A3) ;ONE IS THE BACKGROUND PATTERN
CLR.L PNPIXPAT(A3) ;ONE IS THE PEN PATTERN
CLR.L FILLPIXPAT(A3) ;AND ONE IS THE FILL PATTERN
MOVE.L A3,-(SP) ;PUSH GRAFPORT
jsrROM INITCOLORSTUFF ;AND INITIALIZE PATTERNS AND COLORS
;---------------------------------------------------
;
; NOW DRAW THE PICTURE:
; REPEAT UNTIL NOT PicItem1(playState);
;
DRAWPIC MOVE #PICTVERSION,PLAYSTATE+PLAYVERSION(A6) ;DEFAULT TO OLD PICTURE
MOVE.L MYPICTURE(A6),A0 ;GET PICTURE HANDLE <16Jun88 BAL>
_HGETSTATE ;GET AND SAVE STATE <16Jun88 BAL>
MOVE D0,-(SP) ; <16Jun88 BAL>
_HLOCK ;LOCK IT DOWN <16Jun88 BAL>
MORE
if TheFuture then ; <124> Take out of current builds
cmp.w #AbortPicPlayBackErr,qdErr ;abort if special error <121>
beq.s Done ; <121>
endif ; <124>
CLR.B -(SP) ;MAKE ROOM FOR FCN RESULT
PEA PLAYSTATE(A6) ;PUSH ADDR OF PLAYSTATE
_PicItem1 ;DRAW ONE PICTURE ITEM
MOVE.B (SP)+,D0 ;POP BOOLEAN RESULT
BNE.S MORE ;LOOP TILL FALSE
;-----------------------------------------------------
;
; DISCARD HANDLES AND RESTORE GRAFPORT STATE
;
DONE MOVE.L MYPICTURE(A6),A0 ;GET PICTURE HANDLE <16Jun88 BAL>
MOVE (SP)+,D0 ;GET SAVED STATE <16Jun88 BAL>
_HSETSTATE ;RESTORE STATE <16Jun88 BAL>
MOVE.L PLAYSTATE+THECLIP(A6),A0 ;GET THECLIP RGNHANDLE
_DisposHandle ;DISCARD IT
MOVE.L PLAYSTATE+FontMappingTbl(A6),A0 ;get the fontID association table
_DisposHandle ;DISCARD IT
TST PORTBITS+ROWBYTES(A3) ;IS IT A NEW PORT?
BMI.S @NEWPORT ;=>YES, DISPOSE PIXPATS
MOVE.L PLAYSTATE+TEMPPIXPAT(A6),-(SP) ;ELSE PUSH TEMP PIXPAT
_DISPOSPIXPAT ;AND DISCARD IT
BRA.S DONE1 ;=>DISPOSE COMMON STUFF
@NEWPORT MOVE.L BKPIXPAT(A3),-(SP) ;PUSH THE BACKGROUND PATTERN
_DISPOSPIXPAT ;AND DISCARD IT
MOVE.L PNPIXPAT(A3),-(SP) ;PUSH THE PEN PATTERN
_DISPOSPIXPAT ;AND DISCARD IT
MOVE.L FILLPIXPAT(A3),-(SP) ;PUSH THE FILL PATTERN
_DISPOSPIXPAT ;AND DISCARD IT
DONE1 MOVE.L CLIPRGN(A3),A0 ;GET TEMPCLIP
_DisposHandle ;DISCARD IT
LEA SAVEPORT(A6),A0 ;SRC = SAVEPORT
MOVEQ #PORTREC/2-1,D0 ;INIT DBRA COUNT
DONELP MOVE.W (A0)+,(A3)+ ;COPY A WORD INTO THEPORT
DBRA D0,DONELP ;LOOP ENTIRE PORT
;---------------------------------------------------
;
; RESTORE THE GLYPH RENDERING STATE
;
IF hasGlyphState THEN
move.b saveOutline(a6),-(sp) ; push saved outline preferred flag
_SetOutlinePreferred ; restore saved outline preferred
move.b savePreserve(a6),-(sp) ; push saved preserve glyph flag
_SetPreserveGlyph ; restore saved preserve glyph
move.b saveFractional(a6),-(sp) ; push saved fractional widths flag
_SetFractEnable ; restore saved fractional widths
move.b saveUnscaled(a6),-(sp) ; push saved scale disable flag
_SetFScaleDisable ; restore saved scale disable
ENDIF
;---------------------------------------------------
;
; RESTORE THE LINE-LAYOUT STATE
;
IF SCRIPT_CHAR_EXTRA THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals. <54>
move.l saveQdChExtra(a6),qdChExtra(a0) ; restore character extra amount. <54>
move.l saveQdRunSlop(a6),qdRunSlop(a0) ; restore run slop amount. <54>
ENDIF
;---------------------------------------------------
;
; RESTORE GLOBAL VARS AND QUIT
;
CLR.L PATALIGN(A4) ;RESTORE PATALIGN TO (0,0)
CLR.L PLAYPIC(A4) ;SET PLAYPIC TO NIL
CLR.L PLAYINDEX(A4) ;AND PLAYINDEX TO 0
GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'DRAWPICT'
;=========================================================================================
;=========================================================================================
;
; Patch to add PicItem1. PicItem1 dispatches the picture drawing opcodes. Since we are
; only changing opcode $2C and opcode $03, we handle them at the top. If we have any
; other opcode, we jump to the ROM version.
;
; But wait! Don't forget to check for the $2C opcode which is used to record the line-
; layout state for the Script Manager.
;
; Even better! We now check for the $2E opcode which is used to record the state of the
; Font Manager and TrueType for glyph rendering.
;
;=========================================================================================
;=========================================================================================
PicItem1 FUNC EXPORT
;------------------------------------------------------------------
;
; FUNCTION PicItem1(VAR playState: PicPlayRec): BOOLEAN;
;
; Draws one picture item, updating playState and thePort.
; Returns FALSE when an endPic opCode is encountered.
; The only state modified other than thePort and playState is patAlign.
;
; When reading from an NPIC, skips to word boundary before fetching
; word-long opcode.
PicItemContinue EQU $31F80
PicItemDone EQU $32B48
ciGetByte EQU $32B60
ciGetWord EQU $32B80
ciGetLong EQU $32B90
ciGetPicData EQU $32BA0
ciGetPicOp EQU $32ABE
ciIgnoreShort EQU $3236E
ciIgCount EQU $3237E
ciCALL1 EQU $32B16
ciGOIGCOUNT EQU $32378
ciBitsOp2 EQU $326A6
ciContinueBitsOp EQU $3268C
ciGETPICTABLE EQU $32F70
ciMAPRATIO EQU $33AE0
ciDoBits EQU $32732
ciBadBits EQU $327AE
ciAfterLstBand EQU $3296A
ciAbort EQU $32B3A
ciGetHndl EQU $32AE6
TxFontOpCode EQU $0003
TxRatioOpCode EQU $0010
FontIDOpCode EQU $002C
LayoutOpCode EQU $002D
GlyphOpCode EQU $002E
UserQDOpCode EQU $00A2
;--------------------------------------------
;
; OFFSETS WITHIN A PICTURE PLAY STATE RECORD:
;
THERECT EQU 0 ;RECT
PENLOC EQU THERECT+8 ;POINT
TEXTLOC EQU PENLOC+4 ;POINT
OVALSIZES EQU TEXTLOC+4 ;POINT
FROMRECT EQU OVALSIZES+4 ;RECT
TORECT EQU FROMRECT+8 ;RECT
NUMER EQU TORECT+8 ;POINT
DENOM EQU NUMER+4 ;POINT
THECLIP EQU DENOM+4 ;RGNHANDLE
USERCLIP EQU THECLIP+4 ;RGNHANDLE
PLAYVERSION EQU USERCLIP+4 ;PICTURE VERSION
TXHFRAC EQU PLAYVERSION+2 ;FRACTIONAL TEXT POSITION
NEWHFRAC EQU TXHFRAC+2 ;UPDATED FRACTION RECIEVED
TEMPPIXPAT EQU NEWHFRAC+2 ;PIXPAT FOR PLAYING NEW PICS IN OLD PORTS
FontMappingTbl EQU TEMPPIXPAT+4 ;Handle to array of old,new font id pairs
PSreserve1 EQU FontMappingTbl+4 ;reserved
PSreserve2 EQU PSreserve1+4 ;reserved
PLAYREC EQU PSreserve2+4 ;TOTAL SIZE
;
; params:
;
PARAMSIZE EQU 4
RESULT EQU PARAMSIZE+8 ;BOOLEAN
PLAYSTATE EQU RESULT-4 ;LONG, PICHANDLE
;
; locals:
;
HANDLE1 EQU -4 ;HANDLE
HANDLE2 EQU HANDLE1-4 ;HANDLE
TmpHANDLE1 EQU HANDLE2-4 ;temporary memory handle <1.5> BAL
DSTRECT EQU TmpHANDLE1-8 ;RECT (MUST BE BEFORE SRCRECT)
SRCRECT EQU DSTRECT-8 ;RECT (MUST FOLLOW DSTRECT)
SRCPIX EQU SRCRECT-PMREC ;PIXMAP
SRCBITS EQU SRCPIX-BITMAPREC ;BITMAP
SAMEFLAG EQU SRCBITS-2 ;BOOLEAN
NEWPT EQU SAMEFLAG-4 ;LONG
TXDATA EQU NEWPT-256 ;UP TO 256 CHARACTERS,
;ALSO USED FOR PACKBUF !!!
SRCPTR EQU TXDATA-4 ;LONG
DSTPTR EQU SRCPTR-4 ;LONG
SAVEDSP EQU DSTPTR-4 ;LONG
VARSIZE EQU SAVEDSP ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGISTERS
MOVE.L SP,SAVEDSP(A6) ;REMEMBER STACK FOR ABORT
clr.l tmpHandle1(a6) ;don't dispose it again
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
MOVE.L PLAYSTATE(A6),A2 ;POINT TO PLAYSTATE RECORD
; GET PICTURE OPCODE AND CHECK FOR END OF PICTURE.
MOVE.B #1,RESULT(A6) ;Assume NOT END OF PICTURE
jsrROM ciGetPicOp ;READ OPCODE INTO D0
if TheFuture then ; <124> Do only in the future
cmp.w #AbortPicPlayBackErr,qdErr ;abort if special error <121>
beq Done ; <121>
endif ; <124>
cmp #TxFontOpCode, d0
beq DoTxFontOpCode
cmp #TxRatioOpCode, d0 ;is it font/ID opcode?
beq DoTxRatioOpCode
cmp #FontIDOpCode, d0 ;is it font/ID opcode?
beq DoFontIDOpCode
IF SCRIPT_CHAR_EXTRA THEN
cmp #LayoutOpCode,d0 ;line-layout opcode?
beq DoLayoutOpCode ;yes -> load line-layout state.
ENDIF
IF hasGlyphState THEN
cmp #GlyphOpCode,d0 ; glyph state opcode?
beq DoStateOpCode ; yes, glyph state information
ENDIF
;
; Check for 90, 91, 98, 99, 9A, and 9B. If color table is zero, don't load it.
;
cmp #$90,d0
blt.s @NotUs
cmp #$9B,d0
ble.s @DoBitsOpCode
@NotUs
CLR.B RESULT(A6) ;ASSUME END OF PICTURE
jmpROM PicItemContinue ;BacktoRom
@DoBitsOpCode
move d0,d7
and #$07,d7 ;get verb from low nibble
BITSOP CMP #3,D7 ;CHECK OPCODE <16Jun88 BAL>
BGT IGNORESHORT ;=>READ WORD LENGTH + DATA
CMP #1,D7 ;IS IT INDEXED <16Jun88 BAL>
BLE.S @IND ;YES DON'T SKIP BOGUS LONG <16Jun88 BAL>
jsrROM ciGETLONG ;GET BOGUS LONG FROM PICTURE <16Jun88 BAL>
@IND jsrROM ciGETWORD ;GET ROWBYTES FROM PICTURE
MOVE D0,SRCPIX+ROWBYTES(A6) ;SAVE ROWBYTES
MOVEQ #BITMAPREC-6,D1 ;GET SIZE OF BITMAP
MOVE D0,D6 ;IS IT A BITMAP OR A PIXMAP?
BPL.S BITSOP1 ;=>IT'S A BITMAP
MOVEQ #PMREC-6,D1 ;GET SIZE OF PIXMAP
BITSOP1 PEA SRCPIX+BOUNDS(A6) ;PUSH ADDR OF SRCPIX.BOUNDS
MOVE D1,-(SP) ;PUSH BYTECOUNT
jsrROM ciGETPICDATA ;GET BITMAP/PIXMAP
clr.w SRCPIX+pmVersion(A6) ; assume 24 bit addressing
; IF IT'S A PIXMAP, THEN ALLOCATE A COLOR TABLE AND GET IT FROM THE PICTURE
TST D6 ;IS IT A PIXMAP?
BPL.S BITSOP2 ;=>NO, DON'T GET TABLE
move.l srcpix+pmTable(a6),d6 ;Get color table from record <28> <KON 28NOV90>
clr.l srcPix+PMTable(a6) ;assume no clut <12Jul88 BAL>
BTST #1,D7 ;IS IT DIRECT DATA? <16Jun88 BAL>
bne.s BITSOP2 ;yes, no CLUT <12Jul88 BAL>
@GETLUT MOVEQ #CTREC,D0 ;GET SIZE OF COLOR TABLE
_NewHandle ;assume it works....
; JSR RNEWHANDLE ;GET A HANDLE FOR IT
MOVE.L A0,SRCPIX+PMTABLE(A6) ;SAVE COLOR TABLE HANDLE
MOVE.L A0,-(SP) ;PUSH COLOR TABLE HANDLE
jsrROM ciGETPICTABLE ;READ COLOR TABLE INTO HANDLE
tst.l d6 ;was color table NIL?
bne.s BitsOp2 ;no, continue
;
; Color table was NIL on record. If it's a dummy CTable, throw it away. Value field
; of $4B4F in value field of 0th entry signals dummy table.
;
move.l srcPix+pmTable(a6),a0
move.l (a0),a2 ;get ptr to color table
cmp.w #cTabSignature,ctTable(a2) ;signature there?
bne.s BITSOP2 ;no, then skip
_DisposHandle ;yes, throw ctable away
clr.l srcPix+pmTable(a6)
BitsOp2
if not(TheFuture) then ; <124> Use this old code for present builds
jmpROM ciBitsOp2 ; <124>
endif ; <124>
if TheFuture then ; <124> Use this only in TheFuture builds
PEA SRCRECT(A6) ;PUSH ADDR OF SRCRECT
MOVE #16,-(SP) ;PUSH BYTECOUNT = 16
jsrROM ciGetPicData ;GET SRCRECT,DSTRECT
MOVE.L PLAYSTATE(A6),A2 ;POINT TO PLAYSTATE RECORD
PEA DSTRECT(A6)
PEA FROMRECT(A2)
PEA TORECT(A2)
_MAPRECT ;MAP DSTRECT
PEA SRCPIX(A6) ;PUSH SRCPIX
PEA SRCRECT(A6) ;PUSH ADDR OF SRCRECT
PEA DSTRECT(A6) ;PUSH ADDR OF DSTRECT
jsrROM ciGETWORD ;GET MODE
MOVE D0,-(SP) ;PUSH MODE
CLR.L -(SP) ;ASSUME MASKRGN = NIL
BTST #0,D7 ;IS MASKRGN USED ? <16Jun88 BAL>
BEQ.S NOTRGN ;=> YES, USE NIL RGN
USERGN jsrROM ciGetHndl ;GET MASKRGN INTO HANDLE1
MOVE.L HANDLE1(A6),-(SP) ;PUSH MASKRGN
MOVE.L PLAYSTATE(A6),A2 ;POINT TO PLAYSTATE RECORD
PEA FROMRECT(A2) ;PUSH FROMRECT
PEA TORECT(A2) ;PUSH TORECT
_MAPRGN ;MAP RGN INTO DSTRECT COORDS
MOVE.L HANDLE1(A6),(SP) ;PASS MASKRGN
MOVE.L HANDLE1(A6),HANDLE2(A6) ;AND REMEMBER MASKRGN IN HANDLE2
NOTRGN MOVE SRCPIX+BOUNDS+BOTTOM(A6),D6 ;GET SRCPIX.BOTTOM
SUB SRCPIX+BOUNDS+TOP(A6),D6 ;CALC HEIGHT
MOVE D6,D5 ;COPY HEIGHT
MOVE SRCPIX+ROWBYTES(A6),D0 ;GET BITMAP/PIXMAP ROWBYTES
AND #nuRBMask,D0 ;CLEAR FLAG BITS
MULU D0,D5 ;CALC BITMAP SIZE
; If the memory request fails, go image a band at a time <C946>
MOVE.L D5,D0 ;GET BYTECOUNT
_NewHandle ;ALLOCATE BITS HANDLE
BNE tryBands ;=> error, try a band at a time <C946>
MEMOK MOVE.L A0,HANDLE1(A6) ;REMEMBER IN HANDLE1
_HLock ;LOCK HANDLE1
gotTmpMem
PEA SRCPIX(A6) ;PUSH PIXMAP
MOVE.L A0,-(SP) ;PUSH HANDLE
_GetPMData ;AND READ IN PIXMAP DATA
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <42>
beq.s cleanUpBADBITS
jmpROM ciDoBits
cleanUpBADBITS
add #18,sp ;get rid of parameters to stdBits already pushed
BADBITS
jmpROM ciBADBits
abort
jmpROM ciAbort
tryBands ; Here Begins <C946> 07Nov87 BAL
;--------------------------------------------------------------------------
;
; The NewHandle for the whole pixmap has failed so lets try a divide and conquer:
;
; d5 = byte count of entire pixmap
; d6 = pixmap height
; d7 = maskrgn flag (word)
;
; Now the stack looks as follows:
;
; srcPix 14(sp) \
; srcRect 10(sp) \
; dstRect 6(sp) > parameters to stdBits call
; mode 4(sp) /
; maskRgn <- TOS /
;
move.l d5,d0 ;ask for the whole banana
_NewTempBuffer ;returns a0=handle, d0=size
move.l a0,tmpHandle1(a6) ;store handle for later
move.l a0,Handle1(a6) ;in case we decide to use it
move.l d0,d4 ;remember tmp buffer size in d4
cmp.l d5,d0 ;did we get it all?
bge gotTmpMem ;yes, go take non-banded case
MOVE SRCPIX+ROWBYTES(A6),D5 ;GET BITMAP/PIXMAP ROWBYTES
AND #nuRBMask,D5 ;CLEAR FLAG BITS
ext.l d5 ;get size of one scanline in d5
_PurgeSpace ;determine available contiguous memory (in a0)
move.l a0,d3 ;get largest block size
cmp.l d3,d4 ;is the temp memory block larger?
ble.s @useAppHeap ;no, use app heap instead
move.l d4,d3 ;use temp memory block
divu.l d5,d3 ;d3 is number of scanlines in each band
bne.s @gotMem ;if more than zero scanlines then doit
bra abort ;else abort
@useAppHeap
move.l tmpHandle1(a6),a0 ;get the temp buffer handle
_DisposeTempBuffer ;release it
clr.l tmpHandle1(a6) ;don't dispose it again
divu.l d5,d3 ;d3 is number of scanlines to allocate
beq abort ;sorry, no space
move.l d5,d0 ;get bytes per scanline
mulu.l d3,d0 ;compute handle size
_NewHandle ;allocate the space
bne abort ;couldn't get it -> abort (hard to believe!)
move.l a0,handle1(a6) ;save handle for later
_HLock ;lock it down
@gotMem
move srcPix+bounds+bottom(a6),d6 ;save srcPix.bounds.bottom in d6
move.w srcPix+Bounds+top(a6),d0 ;get srcpix top
add d3,d0 ;compute srcpix bottom = srcpix top+srcBandHght;
move.w d0,srcPix+Bounds+bottom(a6) ;set srcPix bottom
move.w srcRect+top(a6),d0 ;get srcRect top
add d3,d0 ;compute srcRect bottom = srcRect top+srcBandHght;
move.w d0,srcRect+bottom(a6) ;set srcRect bottom
move.w dstRect+bottom(a6),d5 ;save dstRect bottom in d5
move d5,d4 ;copy dstRect.bottom
sub.w dstRect+top(a6),d4 ;d4 is dstRect height
clr.l -(SP) ;make room for fcn result
move d4,-(SP) ;dstRect height
move d6,-(SP) ;srcRect.bottom
move.w srcPix+Bounds+top(a6),d0 ;get srcpix top
sub d0,(sp) ;srcRect height
_FixRatio ;calc vert scale ratio
move.l (SP)+,d0 ;D6 is dst scanlines per src scanline
move.l d0,d4 ;copy in d4
mulu.l d3,d4 ;d4 is dstBandHght
move.w dstRect+top(a6),d2 ;get dstRect.top
swap d2 ;convert to fixed point
clr.w d2 ;
add.l d4,d2 ;compute dstRect bottom = dstRect.top+dstBandHght;
swap d2 ;truncate
move.w d2,dstRect+bottom(a6) ;set dstRect bottom
swap d2 ;back to fixed
;
; Register useage from here on:
;
; D0,D1 scratch A0,A1 scratch
; D2 dstRect.bottom (Fixed) A2 preserves d2 across proc calls
; D3 src band height A3 ThePort
; D4 dst band height (Fixed) A4 StdBits proc
; D5 original dstRect.bottom
; D6 original srcRect.bottom
; D7 maskRgn flag (word),
; bit #31 -> compress data to 1 bit/pixel for bottle necks
;
MOVE.L HANDLE1(A6),A0 ;GET HANDLE1
MOVE.L (A0),SRCPIX+BASEADDR(A6) ;FILL IN BASEADDR
MOVE.L JStdBits,A4 ;ASSUME GRAFPROCS NOT INSTALLED
bclr.l #31,d7 ;clear sign bit of d7.l -> don't make bitmap
MOVE.L GRAFPROCS(A3),d0 ;ARE GRAFPROCS NIL?
beq.s nxtBand ;no bottle neck procs so skip copy to 1-bit
move.l d0,a0 ;point to grafProcs
move.l bitsProc(a0),d0 ;get installed proc
cmp.l a4,d0 ;bitsProc replaced?
beq.s nxtBand ;=>no, skip copy to 1-bit
move.l d0,a4 ;replace stdbits with user's bottle neck proc
; IF ITS AN OLD GRAFPORT AND GRAFPROCS ARE INSTALLED, THEN COPY THE IMAGE TO AN
; OFFSCREEN BITMAP BEFORE CALLING THE GRAFPROC
TST SRCPIX+ROWBYTES(A6) ;IS SRC A PIXMAP?
BPL.S nxtBand ;=>NO, DON'T NEED TO COPY IT
TST PORTBITS+ROWBYTES(A3) ;IS IT AN OLD PORT?
BMI.S nxtBand ;=>NO, NEW GRAFPORT
;
; Construct a bitmap that tracks the srcPix map and shares its baseAddr
;
bset.l #31,d7 ;set flag -> make 1-bit deep bitmap bands
LEA SRCPIX+ROWBYTES(A6),A0 ;POINT TO PIXMAP ROWBYTES
MOVEQ #0,D0 ;CLEAR HIGH WORD
MOVE (A0)+,D0 ;GET ROWBYTES
AND #nuRBMask,D0 ;MASK FLAG BITS
LSL.L #3,D0 ;CONVERT BYTES TO BITS
DIVU SRCPIX+PIXELSIZE(A6),D0 ;GET ROWBITS FOR ONE-BIT COPY
ADD #15,D0 ;ROUND TO NEAREST WORD BOUNDARY
LSR.L #4,D0 ;DIV BY 16 (WORD BOUNDARY)
BEQ BADBITS ;=>TOO NARROW!
ADD D0,D0 ;HERE'S THE REAL ROWBYTES
LEA SRCBITS+ROWBYTES(A6),A1 ;POINT TO BITMAP BOUNDS
MOVE D0,(A1)+ ;COPY ROWBYTES
MOVE.L (A0)+,(A1)+ ;COPY BOUNDS
MOVE.L (A0)+,(A1)+ ;INTO OUR BITMAP
MOVE.L SRCPIX+BaseAddr(A6),SRCBITS+BASEADDR(A6) ;share bits with pixmap
LEA SRCBITS(A6),A0 ;POINT TO BITMAP
MOVE.L A0,14(SP) ;REPLACE PIXMAP WITH BITMAP (params to stdbits)
; Now unpack a full band of the data into srcPix, optionally compress it to a bitmap,
; and then make the stdBits call. Next, advance the src and dest rects and loop for
; all full bands.
;
; Assumes we need more than one band since original newHandle failed.
nxtBand
PEA SRCPIX(A6) ;PUSH PIXMAP
MOVE.L HANDLE1(A6),-(SP) ;PUSH HANDLE
move.l d2,a2 ;preserve d2
_GetPMData ;AND READ IN PIXMAP DATA
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <42>
beq BADBITS ; <42>
TST.L d7 ;convert to 1 bit deep?
BPL.S @1 ;no, skip copybits
PEA SRCPIX(A6) ;POINT TO SRC
PEA SRCBITS(A6) ;POINT TO DST
PEA SRCPIX+BOUNDS(A6) ;POINT TO SRCRECT
MOVE.L (SP),-(SP) ;POINT TO DSTRECT
MOVE #SRCCOPY,-(SP) ;PUSH MODE
CLR.L -(SP) ;NO MASK REGION
_COPYBITS ;PIXMAP -> BITMAP (converted in place)
@1 move.l 14(sp),-(sp) ;duplicate srcPix/srcBits
move.l 14(sp),-(sp) ;duplicate srcRect
move.l 14(sp),-(sp) ;duplicate dstRect
move.w 16(sp),-(sp) ;duplicate mode <BAL/CSD 09Jul88>
move.l 14(sp),-(sp) ;duplicate maskRgn
JSR (a4) ;CALL BITSPROC
move.l a2,d2 ;restore d2
add d3,srcPix+bounds+top(a6) ;bump srcPix.bounds.top
add d3,srcPix+bounds+bottom(a6) ;bump srcPix.bounds.bottom
add d3,srcBits+bounds+top(a6) ;bump srcBits.bounds.top
add d3,srcBits+bounds+bottom(a6) ;bump srcBits.bounds.bottom
add d3,srcRect+top(a6) ;bump srcRect.top
add d3,srcRect+bottom(a6) ;bump srcRect.bottom
move dstRect+bottom(a6),dstRect+top(a6) ;compute dstRect.top = prev dstRect.bottom
add.l d4,d2 ;compute dstRect.bottom = dstRect.top+dstBandHght;
swap d2 ;truncate
move.w d2,dstRect+bottom(a6) ;set dstRect bottom
swap d2 ;back to fixed
cmp srcPix+bounds+bottom(a6),d6
bgt.s nxtBand ;loop for each full scanline band
; Finish up remaining scanlines <= srcBandHght
LstBand move d5,dstRect+bottom(a6) ;pin dstRect.bottom to original dst bottom
move.w d6,srcPix+Bounds+bottom(a6) ;pin srcPix.bottom to original src bottom
move.w d6,srcBits+Bounds+bottom(a6) ;pin srcBits.bottom to original src bottom
move.w d6,srcRect+bottom(a6) ;pin srcRect.bottom to original src bottom
PEA SRCPIX(A6) ;PUSH PIXMAP
MOVE.L HANDLE1(A6),-(SP) ;PUSH HANDLE
_GetPMData ;AND READ IN PIXMAP DATA
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <42>
beq BADBITS ; <42>
jmpROM ciAfterLstBand
endif ; <124> of TheFuture
;---------------- TxFont OpCode $0003 ----------------------
DoTxFontOpCode
XTXFONT LEA TXFONT(A3),A3
jsrROM ciGetWord ;get the old font ID in d0
MOVE.L PLAYSTATE(A6),A2 ;POINT TO PLAYSTATE RECORD
MOVE.L FontMappingTbl(A2),d1 ;get the fontID association table
beq.s @doit ;just use ID as is
move.l d1,a0
move.l (a0),a0
addq #4,a0 ;point to zero based entry count
move.w (a0)+,d1 ;pick up entry count (could be -1)
bmi.s @doit ;no mapping entries
;entries: oldID,newID word pairs
@1 cmp.w (a0),d0 ;entry for this ID?
addq #4,a0 ;bump to next pair
dbeq d1,@1 ;look until the end or we find it
bne.s @doit ;not found: so don't map
move.w -2(a0),d0 ;found: so use new ID
@doit move.w d0,(a3) ;install the font id in the port
BRA Done ;
;---------------- Handle TxRatio Opcode $0010 ----------------------
DoTxRatioOpCode
MOVE.L PLAYSTATE(A6),A3 ;POINT TO PLAYSTATE RECORD
jsrROM ciGETLONG ;GET TEXT NUMER
MOVE.L D0,NUMER(A3) ;INSTALL INTO PLAYSTATE
jsrROM ciGETLONG ;GET TEXT DENOM
MOVE.L D0,DENOM(A3) ;INSTALL INTO PLAYSTATE
;
; Calculate new numer/denom to 32-bits using ConcatRatio.
;
move.w numer+v(a3),d3
move.w toRect+bottom(a3),d4
sub.w toRect+top(a3),d4 ;get height of toRect
swap d3
swap d4
move.w denom+v(a3),d3
move.w fromRect+bottom(a3),d4
sub.w fromRect+top(a3),d4 ;get height of fromRect
bsr ConcatRatio
move.w d3,denom+v(a3)
swap d3
move.w d3,numer+v(a3)
move.w numer+h(a3),d3
move.w toRect+right(a3),d4
sub.w toRect+left(a3),d4 ;get width of toRect
swap d3
swap d4
move.w denom+h(a3),d3
move.w fromRect+right(a3),d4
sub.w fromRect+left(a3),d4 ;get width of fromRect
bsr ConcatRatio
move.w d3,denom+h(a3)
swap d3
move.w d3,numer+h(a3)
bra done
ConcatRatio
;
; takes two 16-bit numer/denom pairs and returns a 16-bit numer/denom
; D3 = numer/denom
; D4 = ToRect/FromRect
;
; Returns answer in D3
;
move.w d3,d0
mulu.w d4,d0 ;has 32-bit denom
swap d3
swap d4
mulu.w d4,d3 ;has 32-bit numer
;
; Need to convert 32-bit ratio (in d3/d0) into 16-bit ratio in d3
;
move.l d0,d1
or.l d3,d1 ;number of bits to mask in high word
bra.s @FifteenBitsYet
;
; shift until we're clear.
;
@loop
lsr.l #1,d3 ;
lsr.l #1,d0
lsr.l #1,d1
@FifteenBitsYet
move.l d1,d4 ;ratio fit in 15 bits?
and.l #$FFFF8000,d4
bne.s @loop ;nope, loop again
swap d3
move.w d0,d3
rts
;---------------- Font/ID binding OpCode $002C ----------------------
DoFontIDOpCode
;
; At this point we have found a non-zero fond ID which we have not seen previously
; so we must add it to the FontMappingTbl handle. If the handle needs to be resized we do that
; here as well.
AddFontToTbl
fontMapChunk equ 20*4
MOVE.L PLAYSTATE(A6),A2 ;POINT TO PLAYSTATE RECORD
MOVE.L FontMappingTbl(A2),d1 ;get the fontID association table
beq ignoreShort ;skip opcode data if no handle
move.l d1,a0
move.l (a0),a1 ;
moveq #0,d0 ;clear out high end
move.w 4(a1),d0 ;get amnt of handle in use
addq.w #1,d0 ;make 1 based
add.w d0,d0
add.w d0,d0 ;4 bytes per entry
addq.w #6,d0 ;hdr size
cmp.l (a1),d0 ;same as size of handle?
blt.s addFontID ;no need to grow list
add.w #fontMapChunk,d0 ;bump handleSize enough for 25 more fonts
move.l d0,(a1) ;save the new size
_SetHandleSize ;grow list
MOVE.L FontMappingTbl(A2),a0 ;get the fontID association table
move.l (a0),a1 ;get fontList handle
tst.w d0 ;did we get it?
beq.s addFontID ;yes, continue
sub.w #fontMapChunk,(a1) ;couldn't grow it.
bra ignoreShort ;skip name stuff
addFontID
move.l a0,a3 ;save fontMappingTbl handle in a3
jsrROM ciGetWord ;get word data length
subq #2,d0 ;get length of fond name (incl. length byte)
MOVE D0,D6 ;SAVE LENGTH IN D6
jsrROM ciGetWord ;get old fond ID
MOVE D0,D7 ;save fond ID in D7
PEA TXDATA(A6) ;PUSH ADDR OF TEXT BUF
MOVE D6,-(SP) ;PUSH BYTECOUNT
jsrROM ciGetPicData ;get the name pstring
PEA TXDATA(A6) ;PUSH ADDR OF font name
PEA NewPt(A6) ;PUSH ADDR OF var font id
_GetFNum ;find the appropriate id for this system
move.w NewPt(a6),d6 ;get new fond ID
beq.s fontDone ;not found, so don't add to table
cmp.w d6,d7 ;does old ID = new ID?
beq.s fontDone ;yes, don't add to table
move.l (a3),a1 ;fontID association table handle in A3
addq.w #4,a1 ;point to number of entries in use - 1
addq.w #1,(a1) ;bump the entry count
move.w (a1)+,d0 ;get new entry count and point to entry array
lea (a1,d0*4),a1 ;point to this 0ld,New pair
move.w d7,(a1)+ ;store old ID
move.w d6,(a1) ;store new ID
fontDone
bra Done
;---------------- Line-layout OpCode $002D --------------------------
IF SCRIPT_CHAR_EXTRA THEN
DoLayoutOpCode
jsrROM ciGetWord ; get the data length.
move.w d0,-(sp) ; save this for later.
jsrROM ciGetLong ; get the character extra.
move.l grafGlobals(a5),a0 ; load quickDraw globals. <54>
move.l d0,qdChExtra(a0) ; restore character extra amount. <54>
jsrROM ciGetLong ; get the run slop.
move.l grafGlobals(a5),a0 ; load quickDraw globals. <54>
move.l d0,qdRunSlop(a0) ; restore run slop amount. <54>
clr.l d0 ; clear a long.
move.w (sp)+,d0 ; load original data length.
sub.l #8,d0 ; extra data included?
beq.s Done ; no -> bail out now.
jsrROM ciIgCount ; yes -> skip that extra data.
ENDIF
;---------------- Glyph State OpCode $002E --------------------------
IF hasGlyphState THEN
DoStateOpCode
jsrROM ciGetWord ; get data length
move.w d0,-(sp) ; save this for later
jsrROM ciGetByte ; get outline preferred flag
move.b d0,-(sp) ; push it on the stack
_SetOutlinePreferred ; set outline preferred state
jsrROM ciGetByte ; get preserve glyph flag
move.b d0,-(sp) ; push it on the stack
_SetPreserveGlyph ; set preserve glyph state
jsrROM ciGetByte ; get fractional widths flag
move.b d0,-(sp) ; push it on the stack
_SetFractEnable ; set fractional widths state
jsrROM ciGetByte ; get scaling disabled flag
move.b d0,-(sp) ; push it on the stack
_SetFScaleDisable ; set scaling disabled state
clr.l d0 ; clear a long
move.w (sp)+,d0 ; load original data length
sub.l #4,d0 ; extra data included?
beq.s Done ; no, bail out now
jsrROM ciIgCount ; yes, skip that extra data.
ENDIF
Done jmpROM PicItemDone
ignoreShort jmpROM ciIgnoreShort
;=========================================================================================
;=========================================================================================
;
; Patch to add OpenCPicture. Patch OpenPicture to allocate storage for putting font
; names in pictures. Patch ClosePicture to dispose of font name storage. Patch StdText
; so it saves the names after an opcode $2C.
;
;=========================================================================================
;=========================================================================================
OpenCPicture FUNC EXPORT
EXPORT OpenPicture
IMPORT HidePen,NewRgn
;------------------------------------------------------
;
; Offsets in parameter block passed to OpenCPicture
;
ppSrcRect EQU 0 ;Rect
ppHRes EQU ppSrcRect+8 ;Fixed
ppVRes EQU ppHRes+4 ;Fixed
ppVersion EQU ppVRes+4 ;Word (=0)
ppReserved EQU ppVersion+2 ;Word
ppReserved2 EQU ppReserved+2 ;Long
PicParamSize EQU ppReserved2+4 ;size of a PICT2 header record
;------------------------------------------------------
;
; New offsets in a PICT2 header record:
;
hdrVersion EQU 0 ;Word (=-2)
hdrReserved EQU hdrVersion+2 ;Word
hdrHRes EQU hdrReserved+2 ;Fixed
hdrVRes EQU hdrHRes+4 ;Fixed
hdrSrcRect EQU hdrVRes+4 ;Rect
hdrReserved2 EQU hdrSrcRect+8 ;Long
picHdrSize EQU hdrReserved2+4 ;size of a PICT2 header record
;------------------------------------------------------------------
;
; FUNCTION OpenCPicture( newHeader: PICT2Header ) : cPicHandle;
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE EQU 4
RESULT EQU PARAMSIZE+8 ;LONG, PICHANDLE
params EQU RESULT-4 ;ptr to input params
SAVEVERSION EQU -2 ;PICTURE VERSION NUMBER
picHdrRec EQU SAVEVERSION-picHdrSize ;PICT2 header record
defaultFrame EQU picHdrRec-8 ;pic frame to be recorded in picture
VARSIZE EQU defaultFrame ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;MAKE STACK FRAME
MOVE #npicVersion,SAVEVERSION(A6) ;SAVE VERSION NUMBER
;copy input parameters into pict 2 header record and compute picFrame
move.l params(a6),a0 ;point to input parameters
move.l ppSrcRect(a0),picHdrRec+hdrSrcRect(a6)
move.l ppSrcRect+bottom(a0),picHdrRec+hdrSrcRect+bottom(a6)
move.l ppHRes(a0),picHdrRec+hdrHRes(a6)
move.l ppVRes(a0),picHdrRec+hdrVRes(a6)
move.w ppVersion(a0),d0 ;orginal version?
bne.s @newversion
move.w #-2,picHdrRec+hdrVersion(a6)
clr.w picHdrRec+hdrReserved(a6)
clr.l picHdrRec+hdrReserved2(a6)
bra.s @computePicFrame
@newversion ;fill out additional fields
move.w d0,picHdrRec+hdrVersion(a6)
move.w ppReserved(a0),picHdrRec+hdrReserved(a6)
move.l ppReserved2(a0),picHdrRec+hdrReserved2(a6)
@computePicFrame
move.l picHdrRec+hdrSrcRect+top(a6),d0 ;get topLeft in d0
move.l picHdrRec+hdrSrcRect+bottom(a6),d1 ;get botRight in d1
move.l d0,defaultFrame+top(a6) ;set default new height
move.l d1,defaultFrame+bottom(a6) ;set default new width
sub.w d0,d1 ;get width in d1.w
move.w d1,d2 ;save width in d2.w
swap d0
swap d1
sub.w d0,d1 ;get height in d1.w
moveq #72,d0
mulu.w d0,d1 ;d1.L = height*72
move.l d1,a0 ;save height*72 in a0
mulu.w d0,d2 ;d2.L = width*72
swap d2
moveq #0,d1 ;extend d1 to long in copy: don't trash high word <KON>
move.w d2,d1
clr.w d2
move.l picHdrRec+hdrHRes(a6),d0
beq.s @skip
divu.l d0,d1:d2 ;d2.w = (width*72)/vRes
move.l picHdrRec+hdrVRes(a6),d0
beq.s @skip
clr.l defaultFrame+top(a6) ;force topLeft to be 0,0
move.w d2,defaultFrame+right(a6) ;right = new width
moveq #0,d2
move.l a0,d1 ;restore d1
swap d1
move.w d1,d2
clr.w d1
divu.l d0,d2:d1 ;d1.w = (height*72)/vRes
move.w d1,defaultFrame+bottom(a6) ;bottom = new height
@skip
BRA.s OPShare ;=>GO USE COMMON CODE
OpenPicture
OpenPictciEntry: EQU $31BFC
OpenPictciDONE: EQU $31D12
;------------------------------------------------------------------
;
; FUNCTION OpenPicture(picFrame: Rect): PicHandle;
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
; the following is defined above...
;
;PARAMSIZE EQU 4
;RESULT EQU PARAMSIZE+8 ;LONG, PICHANDLE
;params EQU RESULT-4 ;ptr to input params
;SAVEVERSION EQU -2 ;PICTURE VERSION NUMBER
;picHdrRec EQU SAVEVERSION-picHdrSize ;PICT2 header record
;defaultFrame EQU picHdrRec-8 ;pic frame to be recorded in picture
;VARSIZE EQU defaultFrame ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;MAKE STACK FRAME
MOVE #pictVersion,SAVEVERSION(A6) ;SAVE VERSION NUMBER
move.l params(a6),a0 ;point to input rect
move.l (a0)+,defaultFrame(a6) ;copy topLeft
move.l (a0),defaultFrame+bottom(a6) ;copy botRight
lea picHdrRec+picHdrSize(a6),a1 ;point to end of hdr record <06Feb90 KON>
CLR.L -(a1) ;CLEAR RESERVED LONG
MOVE.L params(A6),A0 ;POINT TO BOUNDING RECT
MOVE.L BOTTOM(A0),D0 ;GET BOTTOM AS FIXED
CLR D0 ;CLEAR LOW WORD
MOVE.L D0,-(a1) ;PUSH FIXED BOTTTOM
MOVE.L RIGHT(A0),D0 ;GET RIGHT AS FIXED
CLR D0 ;CLEAR LOW WORD
MOVE.L D0,-(a1) ;PUSH FIXED RIGHT
MOVE.L TOP(A0),D0 ;GET TOP AS FIXED
CLR D0 ;CLEAR LOW WORD
MOVE.L D0,-(a1) ;PUSH FIXED TOP
MOVE.L LEFT(A0),D0 ;GET LEFT AS FIXED
CLR D0 ;CLEAR LOW WORD
MOVE.L D0,-(a1) ;PUSH FIXED LEFT
MOVEQ #-1,D0 ;GET -1 AS SIZE
MOVE.L D0,-(a1) ;PUSH LONG SIZE
OPShare MOVEM.L D3/A3-A4,-(SP) ;SAVE REGS
CLR.L RESULT(A6) ;INIT FCN RESULT TO NIL
; Abort OpenPicture if heap doesn't have at least 1500 bytes. <16Jan89 KON>
MOVE.L #1500,D0 ;GET BYTE COUNT
_NewHandle ;AT LEAST 1000 BYTES IN THE HEAP ?
BNE DONE ;NO, RETURN NIL AND QUIT
_DisposHandle ;YES, Discard test handle
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;GET CURRENT GRAFPORT
TST.L PICSAVE(A3) ;ARE WE ALREADY SAVING ?
BNE DONE ;YES, RETURN NIL AND QUIT
_HidePen ;NO, TURN OFF DRAWING
; IF IT'S A NEW GRAFPORT, FORCE NEW PICTURE
TST PORTBITS+ROWBYTES(A3) ;IS IT A NEW GRAFPORT?
BPL.S @OLDGP ;=>NO, OLD GRAFPORT
MOVE #npicVersion,SAVEVERSION(A6) ;ELSE FORCE TO NEW PICTURE
; ALLOCATE PICSAVE RECORD
@OLDGP MOVE.L #npicSaveRec,D0 ;GET BYTE COUNT
_NewHandle ;ALLOCATE PICSAVE RECORD
MOVE.L A0,A4 ;GET RESULT HANDLE
MOVE.L A4,PICSAVE(A3) ;SAVE RESULT IN THEPORT
;
; ALLOCATE PICCLIPRGN (leave on stack for now)
;
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
_NEWRGN ;ALLOCATE A NEW REGION
;
; ALLOCATE THEPIC PICHANDLE
;
MOVE.L #256,D0 ;BYTE COUNT = 256
_NewHandle ;ALLOCATE NEWHANDLE(256)
MOVE.L A0,A1 ;GET THEPIC HANDLE
MOVE.L A1,RESULT(A6) ;PUT HANDLE IN FCN RESULT
;
; NOW FILL THEPIC'S PICSIZE AND PICFRAME
;
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE HANDLE
MOVE.L A1,(A4)+ ;SAVE PICHANDLE IN THEPIC
MOVE.L (A1),A1 ;DE-REFERENCE PICHANDLE
MOVE #10,(A1)+ ;INSTALL PICSIZE = 10
lea defaultFrame(A6),A0 ;POINT TO PICFRAME
MOVE.L (A0)+,(A1)+ ;COPY RECT INTO PICTURE
MOVE.L (A0)+,(A1)+
;
; INIT STATE VARIABLES FOR PICTURE CAPTURE
;
MOVE.L #256,(A4)+ ;PICMAX := 256;
MOVE.L #10,(A4)+ ;PICINDEX := 10
MOVE.L (SP)+,(A4)+ ;INSTALL PICCLIPRGN
CLR.L (A4)+ ;PICBKPAT := WHITE
CLR.L (A4)+
CLR.L (A4)+ ;PICTXFONT = 0, PICTXFACE = []
MOVE #1,(A4)+ ;PICTXMODE := SRCCOPY
CLR (A4)+ ;PICTXSIZE := 0
CLR.L (A4)+ ;PICSPEXTRA := 0.0
MOVE.L #$00010001,D0 ;GET (1,1)
MOVE.L D0,(A4)+ ;PICTXNUMER := (1,1)
MOVE.L D0,(A4)+ ;PICTXDENOM := (1,1)
CLR.L (A4)+ ;PICTXLOC := (0,0)
CLR.L (A4)+ ;PICPNLOC := (0,0)
MOVE.L D0,(A4)+ ;PICPNSIZE := (1,1)
MOVE #8,(A4)+ ;PICPNMODE := PATCOPY
MOVEQ #-1,D0 ;GET SOME BLACK
MOVE.L D0,(A4)+ ;PICPNPAT := BLACK
MOVE.L D0,(A4)+
MOVE.L D0,(A4)+ ;PICFILLPAT := BLACK
MOVE.L D0,(A4)+
CLR.L (A4)+ ;PICTHERECT := (0,0,0,0)
CLR.L (A4)+
CLR.L (A4)+ ;PICOVSIZE := (0,0)
MOVE.L PORTRECT+TOPLEFT(A3),(A4)+ ;PICORIGIN := CURRENT ORIGIN
MOVE.L #blackColor,(A4)+ ;PICFGCOLOR := blackColor
MOVE.L #whiteColor,(A4)+ ;PICBKCOLOR := whiteColor
MOVE SAVEVERSION(A6),(A4)+ ;picVersion := version number
CLR.L (A4)+ ;picRGBFgCol := black
CLR (A4)+
MOVE.L D0,(A4)+ ;picRGBBkCol := white
MOVE D0,(A4)+
MOVE.L #$00008000,(A4)+ ;picChExtra := 0
;picLocHFrac := 1/2
CLR.L (A4)+ ;picRGBOpColor := black
CLR (A4)+
CLR.L (A4)+ ;picRGBHiColor := black
CLR (A4)+
; IF IT'S A NEW PICTURE, ALLOCATE THE PIXEL PATTERNS
CMP #pictVersion,SAVEVERSION(A6) ;is it a pict?
BEQ.S doFontList ;=>yes, skip new stuff
tst portBits+rowBytes(a3) ;is it a new picture in an old grafport? <20Sept90 KON>
bpl.s doFontList ;=>yes, skip new stuff <20Sept90 KON>
MOVEQ #2,D3 ;allocate 3 pixPats
NXTPP CLR.L -(SP) ;make room for function result
sub.l ([PicSave,a3]),a4 ;get offset into picSave record <<BAL 04Apr88>>
_NEWPIXPAT ;get a new pixPat
MOVE.L (SP)+,A0 ;get pixPat handle
add.l ([PicSave,a3]),a4 ;offset into record <<BAL 04Apr88>>
MOVE.L A0,(A4)+ ;save pixPat to picsave record
MOVE.L (A0),A0 ;point at pixPat
MOVE #oldPat,patType(A0) ;init to old pattern
DBRA D3,NXTPP ;=>repeat for all pixPats
;
; Allocate handle for fond id's we have seen so far
;
; Format of picFontList handle is:
; handle size [long]
; # of entries - 1 used [word]
; id1, id2, ... idn
FontListSize equ 50*2
doFontList
moveq #FontListSize+6,d0 ;initial size for 50 entries
_NewHandle
move.l picSave(a3),a1 ;get picSave handle
move.l (a1),a1
move.l a0,picFontList(a1) ;save picFontList handle in picSave record
beq.s @noHandle
move.l (a0),a0 ;point into fontList
moveq #FontListSize+6,d0 ;initial size for 50 entries
move.l d0,(a0)+
clr.l (a0) ; 1 entry, first entry = 0
@noHandle
;
; Clear picQdRunSlop and picQdChExtra
;
move.l picSave(a3),a1 ; load the picSave handle
move.l (a1),a1 ; load the picSave pointer
clr.l picQdChExtra(a1) ; clear the character extra
clr.l picQdRunSlop(a1) ; clear the run slop
; INIT GLYPH STATE TO INVALID
move.l #$80808080,picGlyphState(a1) ; set glyph state to invalid values
; PUT VERSION NUMBER TO PICTURE
MOVEQ #opVersion,D0 ;GET VERSION OPCODE
jsrROM DPutPicOp ;PUT TO PICTURE
MOVE SAVEVERSION(A6),D0 ;GET VERSION NUMBER
CMP #pictVersion,D0 ;IS IT AN OLD PICTURE?
BNE.S @NotPic ;=>NO, NOT AN OLD PICT
jsrROM DPUTPICBYTE ;IF OLD PUT BYTE TO PICTURE
BRA.S DONE ;AND RETURN
; IT'S A NEW PICTURE! PUT VERSION AS WORD, FOLLOW IT WITH HEADER OPCODE
@NotPic MOVE D0,-(SP) ;ELSE PUSH VERSION
jsrROM PUTPICWORD ;AND PUT ENTIRE WORD FOR NEW PICTURES
; HEADER EXTENSION = [OP] [SIZE] [BBOX] [RESERVED]
MOVE #ngHeaderOp,D0 ;GET HEADER OPCODE
jsrROM DPutPicOp ;PUT TO PICTURE
pea picHdrRec(a6) ;PUSH POINTER TO DATA
MOVE #24,-(SP) ;PUSH SIZE OF DATA
jsrROM PUTPICDATA ;AND BLAST IT TO THE PICTURE
DONE MOVEM.L (SP)+,D3/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'OPENPICT'
ENDPROC
UpdatePat PROC EXPORT
ciUpdatePatEntry EQU $32E30
ciPatNew EQU $32E60
;------------------------------------------------------
;
; PROCEDURE UpdatePat(SRCPAT: PTR; SRCPIXPAT: HANDLE;
; SAVEPAT: PTR; SAVEPIXPAT: HANDLE;
; OLDOP,NEWOP: INTEGER);
;
; CHECK TO SEE IF THE SPECIFIED PATTERN NEEDS UPDATING.
; IF SO, PUT THE NEW PATTERN TO THE PICTURE AND RECORD THE
; CHANGE IN THE PICSAVE RECORD.
;
; ASSUMES THAT AN OLD PICTURE WILL ONLY BE RECORDED IN AN OLD GRAFPORT
; AND THAT A NEW PICTURE WILL ONLY BE RECORDED IN A NEW GRAFPORT.
;
; ON ENTRY: A3 = GRAFPORT
; A4 = PICSAVE RECORD
;
PARAMSIZE EQU 20
SRCPAT EQU PARAMSIZE+8-4 ;PTR
SRCPIXPAT EQU SRCPAT-4 ;HANDLE
SAVEPAT EQU SRCPIXPAT-4 ;PTR
SAVEPIXPAT EQU SAVEPAT-4 ;HANDLE
OLDOP EQU SAVEPIXPAT-2 ;WORD
NEWOP EQU OLDOP-2 ;WORD
LINK A6,#0 ;NO LOCAL VARS
MOVEM.L D5/D6,-(SP) ;SAVE WORK REGISTERS
tst portBits+rowBytes(a3) ;in an old grafport? <18Sept90 KON>
bmi.s patnew ;=>yes, skip old stuff <18Sept90 KON>
; CMP #PICTVERSION,PICVERSION(A4) ;IS IT AN OLD PICTURE? <18Sept90 KON>
; BNE.S PATNEW ;=>NEW, CHECK NEW PICTURE <18Sept90 KON>
jmpROM ciUpdatePatEntry
patnew
jmpROM ciPatNew
ENDPROC
;
; <124> Bring this code back for CubeE and TheFuture.
;
if not(TheFuture) then
ClosePicture PROC EXPORT
ciClosePictureEntry: EQU $31D4C
ciClosePictureGoHome: EQU $31D82
cinopp EQU $31D74
;------------------------------------------------------------------
;
; PROCEDURE ClosePicture;
;
MOVEM.L D6-D7/A3,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A3 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A3),A3 ;GET CURRENT GRAFPORT
MOVE.L PICSAVE(A3),D7 ;ARE WE SAVING A PICTURE ?
BEQ.S GOHOME ;NO, OOPS, EXIT
MOVE #opEndPic,D0 ;PUSH ENDPIC OPCODE
jsrROM DPutPicOp ;PUT TO THEPIC
MOVE.L D7,A0 ;GET PICSAVE HANDLE
MOVE.L (A0),A0 ;POINT TO PICSAVE RECORD
move.l picFontList(a0),a0 ;get fontList handle
_DisposHandle
MOVE.L D7,A0 ;GET HANDLE TO PICSAVE RECORD
MOVE.L (A0),A0 ;DE-REFERENCE IT
MOVE.L PICCLIPRGN(A0),D6 ;GET picClipRgn
MOVE.L PICINDEX(A0),D0 ;DID PICTURE OVERFLOW ?
BEQ.S OVERFLO ;YES, CONTINUE
MOVE.L THEPIC(A0),A0 ;NO, GET THEPIC HANDLE
_SetHandleSize ;AND TRIM TO FINAL SIZE
OVERFLO MOVE.L D6,A0 ;GET PICCLIPRGN
_DisposHandle ;DISCARD IT
tst portBits+rowBytes(a3) ;is it in an old grafport? <20Sept90 KON>
bpl.s nopp ;=>yes, skip new stuff <20Sept90 KON>
jmpROM ciClosePictureEntry
nopp jmpROM cinopp
GOHOME jmpROM ciClosePictureGoHome ;AND RETURN
endif ; <124>
;ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª
;ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª
;
; Patches for Alpha Channel Fixes
;
;ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª
;ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª
;Patch for GWorld.a
RectRgn PROC EXPORT
ciRectRgn EQU $361D0
ciNGWRectRgn EQU $3FE7E
ciNGWSkip EQU $3FE8C
pixelShift equ -2 ; WORD, pixel shift amount
resPref equ pixelShift-2 ; WORD, device's preferred resolution
bytesPerRow equ resPref-2 ; WORD, rowBytes of offscreen pixmap
offscreenBufH equ bytesPerRow-4 ; LONG, handle to the offscreen buffer
offscreenPixMap equ offscreenBufH-4 ; LONG, handle to the offscreen pixmap
offscreenCTable equ offscreenPixMap-4 ; LONG, handle to the offscreen color table
offscreenDevice equ offscreenCTable-4 ; LONG, handle to the offscreen device
offscreenITable equ offscreenDevice-4 ; LONG, handle to the offscreen inverse table
offscreenPortH equ offscreenITable-4 ; LONG, handle to the offscreen port
offscreenPort equ offscreenPortH-4 ; LONG, pointer to the offscreen port
cmpRA ciNGWRectRgn,(SP) ;is call of RectRgn from NewGWorld?
BNE.S @toROM ;no, go to RectRgn
ADDQ #4,SP ;throw away return address
jsrROM ciRectRgn ;call RectRgn
MOVE.L offscreenPort(A6),A0 ;get pointer to port
MOVE.L grafVars(A0),-(SP) ;push grafVars handle
_ResizeGrafVars ;make the grafVars bigger
jmpROM ciNGWSkip ;jump to just after GrafVars resizing code
@toROM jmpROM ciRectRgn
;Patches from Rects.a
PushVerb PROC EXPORT
;----------------------------------------------------------
;
; PUSH A MODE AND A PATTERN, BASED ON VERB
; ENTER WITH VERB IN D7, GRAFGLOBALS IN A4, THEPORT IN A3.
;
; CLOBBERS A0-A1/D0/D2
;
ciPushVerb EQU $2C41C
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE #8,-(SP) ;PUSH MODE = PATCOPY (IE. DEFAULT)
CMP.B #1,D7 ;CASE ON VERB
BLE.S PAINT1
MOVEQ #0,D1 ;push clear pen mode
_GetStreamMode ;clear alpha mode bits
MOVE.L A1,A0
jmpROM ciPushVerb
PAINT1 MOVE PNMODE(A3),D1 ;push the pen mode
_GetStreamMode ;extract alpha mode bits
OR D1,(SP) ;push mode, but leave the pattern bit set
PEA PNPAT(A3) ;PUSH PAT = PNPAT
JMP (A1) ;RETURN TO CALLER
ENDPROC
;----------------------------------------------------------------
;
; Dispatcher for alpha channel utility routines (Trap $ABC0)
;
AlphaDispatch PROC EXPORT
ciRSetHSize EQU $31450
JMP @dispatch(PC,D0.W*4)
@dispatch
BRA.W AlphaVersion
BRA.W SetForeStream
BRA.W SetForeTransparency
BRA.W SetBackStream
BRA.W SetBackTransparency
BRA.W GetForeStream
BRA.W GetForeTransparency
BRA.W GetBackStream
BRA.W GetBackTransparency
BRA.W ResizeGrafVars
BRA.W GetStreamMode
;
; FUNCTION AlphaVersion:INTEGER;
;
AlphaVersion
MOVE.W #$0100,4(SP) ;return version 1.0
RTS
;
; PROCEDURE SetForeStream(streamID: LongInt);
; PROCEDURE SetBackStream(streamID: LongInt);
;
SetForeStream
MOVEQ #foreStream,D1 ;point at foreStream/foreRatio in grafvars
BRA.S SetStream ;jump into common code
SetBackStream
MOVEQ #backStream,D1 ;point at backStream/backRatio in grafvars
SetStream
BSR.S SetSub
BEQ.S @exit
MOVE.L 4(SP),(A0) ;move stream from stack to grafvars
@exit RTD #4 ;clean off stack and return
;
; PROCEDURE SetForeTransparency(streamRatio: INTEGER);
; PROCEDURE SetBackTransparency(streamRatio: INTEGER);
;
SetForeTransparency
MOVEQ #foreRatio,D1 ;point at foreStream/foreRatio in grafvars
BRA.S SetTrans ;jump into common code
SetBackTransparency
MOVEQ #backRatio,D1 ;point at backStream/backRatio in grafvars
SetTrans
BSR.S SetSub
BEQ.S @exit
MOVE.W 4(SP),(A0) ;move ratio from stack to grafvars
@exit RTD #2 ;clean off stack and return
SetSub MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @exit ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @exit ;if null, exit
MOVE.L D0,A0 ;move grafvars handle to more useful register
MOVE.L (A0),A0 ;deref it
BTST #PmNewGVBit-8,pmFlags(A0) ;check for new grafvars flag
BNE.S @1 ;if it was set, no need to grow grafvars
MOVE.L D0,-(SP) ;save grafvars handle
MOVE.L D0,-(SP) ;push grafvars handle for resize call
_ResizeGrafVars ;grow grafvars to new size
MOVE.L (SP)+,A0 ;restore grafvars handle
MOVE.L (A0),A0 ;deref it again
@1: ADD.W D1,A0 ;bump to field being modified
ST D0 ;set do it flag to true
RTS
@exit CLR D0 ;set do it flag to false
RTS
;
; PROCEDURE GetForeStream: INTEGER;
; PROCEDURE GetBackStream: INTEGER;
;
GetForeStream
MOVEQ #foreStream,D1 ;point at foreStream in grafvars
BRA.S GetStream ;jump into common code
GetBackStream
MOVEQ #backStream,D1 ;point at backStream in grafvars
GetStream
MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @default ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @default ;if null, return default info
MOVE.L D0,A0 ;move grafvars handle to more useful register
MOVE.L (A0),A0 ;deref it
BTST #PmNewGVBit-8,pmFlags(A0) ;check for new grafvars flag
BEQ.S @default ;if it was clear, return default info
ADD.W D1,A0 ;bump to either foreStream or backStream
MOVE.L (A0),4(SP) ;move stream from grafvars to user variable
RTS
@default
CLR.L 4(SP) ;move default stream to user variable
RTS
;
; PROCEDURE GetForeTransparency: INTEGER;
; PROCEDURE GetBackTransparency: INTEGER;
;
GetForeTransparency
MOVEQ #foreRatio,D1 ;point at foreRatio in grafvars
BRA.S GetTrans ;jump into common code
GetBackTransparency
MOVEQ #backRatio,D1 ;point at backRatio in grafvars
GetTrans
MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @default ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @default ;if null, return default info
MOVE.L D0,A0 ;move grafvars handle to more useful register
MOVE.L (A0),A0 ;deref it
BTST #PmNewGVBit-8,pmFlags(A0) ;check for new grafvars flag
BEQ.S @default ;if it was clear, return default info
ADD.W D1,A0 ;bump to either foreStream or backStream
MOVE.W (A0),4(SP) ;move ratio from grafvars to user variable
RTS
@default
CLR.W 4(SP) ;move default ratio to user variable
RTS
;
; On Entry:
; (on stack): grafvars handle
;
; ONLY TRASHES D0/A0
;
ResizeGrafVars
MOVE.L 4(SP),A0 ;get grafVars handle
MOVE.L (A0),A0 ;deref grafvars handle
BSET #PmNewGVBit-8,pmFlags(A0) ;check new grafvars flag and set it if not already
BNE.S @exit ;if it was set, then we are too
MOVE.L 4(SP),A0 ;get grafVars handle agian
MOVE.L #newGrafVarRec,D0 ;get size of new grafvars
jsrROM ciRSetHSize ;set the handle to be that size
MOVE.L (A0),A0 ;deref again
LEA foreStream(A0),A0 ;bump to beginning of our stuff
CLR.L (A0)+ ;clear foreStream
CLR.L (A0)+ ;clear foreRatio, half of backStream
CLR.L (A0)+ ;clear half of backStream, backRatio
CLR.W (A0)+ ;clear stream mode and filler
@exit RTD #4 ;all done
;
; On Entry:
; D1: penmode (not necessarily from the current port)
;
; On Exit:
; D1: penmode stripped of alpha transfer bits
;
GetStreamMode
MOVE.L grafGlobals(A5),A0 ;point to QuickDraw globals
MOVE.L thePort(A0),A0 ;get pointer to current port
TST portBits+rowBytes(A0) ;new port?
BPL.S @exit ;no, then don't access grafVars
MOVE.L grafVars(A0),D0 ;get grafVars handle from port
BEQ.S @exit ;if null, exit
MOVE.L D0,-(SP) ;save copy of grafvars handle
MOVE.L D0,-(SP) ;put grafVars handle on stack
_ResizeGrafVars ;make sure grafvars are big enough
MOVE.L (SP)+,A0 ;get grafVars handle off stack
MOVE.L (A0),A0 ;dereference it
MOVE.W D1,D0 ;make copy of penmode
LSR.W #8,D0 ;right align alpha bits
AND.W #3,D0 ;mask off all but alpha bits
MOVE.B D0,streamMode(A0) ;put alphamode into streamMode
@exit AND.W #$FCFF,D1 ;remove alpha bits from penmode
RTS ;return stripped penmode
;
; On Entry:
; (on stack): pointer to streamID and ratio
; (on stack): pointer to where to put
; alphamask (long) and alphacolor (long)
;
StreamToMask PROC EXPORT
MOVE.L 8(SP),A0 ;get pointer to streamID/ratio
MOVE.L 4(SP),A1 ;get pointer to result destination
MOVE.W 4(A0),D0 ;get ratio
TST.L (A0) ;check if stream is graphics (zero)
BEQ.S @1 ;yes, skip
NOT.W D0 ;no, reverse context of transparency
@1: MOVE.W D0,D1
SWAP D0
MOVE.W D1,D0
MOVE.L THEGDEVICE,A0 ;get handle of current gdevice
MOVE.L (A0),A0 ;deref it
MOVE.L gdPMap(A0),A0 ;get handle of gdevice's pixmap
MOVE.L (A0),A0 ;deref it
MOVE.W pmPixelSize(A0),D1 ;get its pixel size
CMP #16,D1 ;is it 16-bits per pixel?
BEQ.S @16bits
MOVE.L MaskBC,D1 ;get 32-bits per pixel not mask
BRA.S @2
@16bits MOVE.L #$7FFF7FFF,D1 ;get 16-bits per pixel not mask
@2: NOT.L D1 ;reverse the mask
AND.L D1,D0 ;mask alpha color
MOVE.L D1,(A1)+ ;save alphamask
MOVE.L D0,(A1)+ ;save alphacolor
RTD #8
if not(TheFuture) then
;Patches from Patterns.a
PatExpand PROC EXPORT
ciRSetHSize EQU $31450
ciGotCopy EQU $30972
ciNEWDONE EQU $30A96
ciNOTOLD EQU $30A9E
&CurFile SETC 'PATEXPAND'
INCLUDE 'DrawingVars.a'
;-------------------------------------------------------------
PARAMSIZE EQU 0
TWOPAT EQU -16 ;ROOM FOR TWO COPIES OF PAT
SAVESTK EQU TWOPAT-4 ;ROOM TO SAVE STACK POINTER
ROTSIZE EQU SAVESTK-2 ;SCANLINE SIZE FOR ROTATION
ROTSHIFT EQU ROTSIZE-2 ;ROTATE AMOUNT
GGLOBALS EQU ROTSHIFT-4 ;POINTER TO GRAFGLOBALS
SAVEA5 EQU GGLOBALS-4 ;PLACE TO SAVE A5
VARSIZE EQU SAVEA5 ;TOTAL BYTES OF LOCAL VARS
;------------------------------------------------------------------
;
; IF OLD PATTERN, ALLOCATE A BUFFER ON THE STACK AND POINT TO IT.
; IF NEW PATTERN, GO EXPAND IF NECESSARY.
;
TST.B NEWPATTERN(A6) ;IS IT A NEW PATTERN?
BNE NEWPATEXPAND ;=>YES, EXPAND PIXELPAT
; ALLOCATE AN EXPAND BUFFER ON THE STACK FOR USE BY CALLER
DOOLD MOVE.L (SP)+,A0 ;GET RETURN ADDRESS
MOVEQ #64,D0 ;MINIMUM BUFFER IS 64 BYTES
MOVE DSTSHIFT(A6),D1 ;GET DEPTH SHIFT
subq #3,D1 ;DEPTHS 1-8 OK @@@@ BAL 10Apr88
ble.S GETBUF ;=>SO GET THE PATTERN BUFFER @@@@ BAL 10Apr88
LSL D1,D0 ;ELSE DOUBLE FOR 16, QUAD FOR 32
GETBUF SUB D0,SP ;MAKE THE BUFFER (LONG ALIGNED)
MOVE.L SP,EXPAT(A6) ;POINT TO PATTERN BUFFER
MOVE.L A0,-(SP) ;REPLACE RETURN ADDRESS
PSHARE LINK A4,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D6/A2-A3/A5,-(SP) ;SAVE REGS
MOVE LOCMODE(A6),D0 ;GET MODE
MOVE DSTPIX+BOUNDS+LEFT(A6),D2 ;GET GLOBAL-LOCAL OFFSET (PIXELS)
MOVE.L FCOLOR(A6),D3 ;GET CURRENT FG COLOR
MOVE.L BCOLOR(A6),D4 ;GET CURRENT BK COLOR
MOVE DSTSHIFT(A6),D5 ;GET SHIFT FOR PIXEL DEPTH
MOVE.L LOCPAT(A6),A0 ;GET PATTERN
LEA PATROW(A6),A1 ;AND DATA DST
AND #$F3,D0 ;TURN OFF PAT, INVERT BITS
BEQ.S GOTCOPY ;=>IT'S COPY MODE
BTST #5,D0 ;is it a new mode?
BNE.S GotCopy
; MOVEQ #-1,D3 ;ELSE FGCOLOR = BLACK
MOVE.L alphaMask(A6),D3
MOVEQ #0,D4 ;AND BKCOLOR = WHITE
GotCopy jmpROM ciGotCopy
NEWPATEXPAND
;----------------------------------------------------------------
;
; NEWPATEXPAND -- EXPAND A PIXELPAT, IF NECESSARY
;
; NOTE: STACK FRAME LINKED USING A4 SO NORMAL FRAME STILL IN A6
;
LINK A4,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D6/A2-A3/A5,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A4) ;SAVE STACK POINTER
MOVE.L GRAFGLOBALS(A5),A3 ;POINT TO QUICKDRAW GLOBALS
MOVE.L A3,GGLOBALS(A4) ;SAVE IN STACK FRAME
MOVE.L A5,SAVEA5(A4) ;AND SAVE GLOBAL POINTER
MOVE.L LOCPAT(A6),A0 ;GET THE PIXPAT HANDLE POINTER
MOVE.L (A0),A0 ;GET THE PIXPAT HANDLE
MOVE.L (A0),A0 ;GET THE PIXPAT POINTER
TST PATTYPE(A0) ;IS IT AN OLD PATTERN?
BNE.S NOTOLD ;=>NO, CHECK FOR EXPANSION OF NEW PAT
;---------------------------------------------------------
;
; IF OLD PATTERN, USE SHARED CODE TO EXPAND IT
;
MOVE.L PATXDATA(A0),A0 ;GET THE EXPANDED DATA HANDLE
MOVEQ #64,D0 ;MINIMUM BUFFER IS 64 BYTES
MOVE DSTSHIFT(A6),D1 ;GET DEPTH SHIFT
subq #3,D1 ;DEPTHS 1-8 OK @@@@ BAL 10Apr88
ble.S BUFOK ;=>SO GET THE PATTERN BUFFER @@@@ BAL 10Apr88
LSL.L D1,D0 ;ELSE DOUBLE FOR 16, QUAD FOR 32
BUFOK jsrROM ciRSetHSize
MOVE.L (A0),d0 ;get master pointer @@@@ BAL 10Apr88
_rTranslate24To32 ;mask off high byte @@@@ BAL 10Apr88
move.l d0,EXPAT(A6) ;SAVE POINTER TO EXPAND DATA AREA
;*** LEAVE IT UNLOCKED
MOVE.L LOCPAT(A6),A0 ;GET PIXPAT HANDLE POINTER
MOVE.L A0,-(SP) ;SAVE PIXPAT HANDLE POINTER
MOVE.L (A0),A0 ;GET HANDLE TO PIXPAT
MOVE.L (A0),A0 ;GET POINTER TO PIXPAT
MOVE.L PATDATA(A0),A0 ;GET HANDLE TO DATA
MOVE.L (A0),A0 ;GET POINTER TO DATA
MOVE.L A0,LOCPAT(A6) ;SET UP POINTER TO SRC DATA
JSR PSHARE ;AND CALL COMMON CODE
MOVE.L (SP)+,LOCPAT(A6) ;RESTORE PATTERN HANDLE
NEWDONE jmpROM ciNEWDONE
NOTOLD jmpROM ciNOTOLD
endif ;not(TheFuture)
;Patches from DrawLine.a
;----------------------------------------------------------------
;
; PROCEDURE DRAWLINE(P1,P2: POINT);
;
; DRAWS A LINE CLIPPED TO CURRENT PORT'S CLIPRGN AND VISRGN
;
; P1 AND P2 ARE GIVEN IN LOCAL COORDINATES OF THEPORT.
;
DrawLine PROC EXPORT
; IMPORT SHFTTBL
Export FastLine,FastSlant
ciDrawLine EQU $29A06
ciSHFTTBL EQU $304B6
ciGOHOME EQU $29E80
&CurFile SETC 'DRAWLINE'
INCLUDE 'DrawingVars.a'
PARAMSIZE EQU 8 ;SIZE OF PARAMETERS
P1 EQU PARAMSIZE+8-4 ;POINT
P2 EQU P1-4 ;POINT
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
CLR.L DSTMASKBUF(A6) ;ASSUME NO MASK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L WIDEOPEN(A0),BIGRGN(A6) ;STASH WIDEOPEN IN BIGRGN
MOVE.L THEPORT(A0),A3 ;POINT TO CURRENT GRAFPORT
TST PNVIS(A3) ;IS PNVIS NEGATIVE ?
BLT GOHOME ;YES, QUIT
MOVE.W PNMODE(A3),D1
_GetStreamMode
MOVE.W D1,LOCMODE(A6)
MOVE.L A3,PORT(A6) ;SAVE PORT FOR LATER
;----------------------------------------------------------------
;
; 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 DSTBITS TO PIXMAP
; (A5 must contain global ptr)
;
LEA PORTBITS(A3),A1 ;GET POINTER TO DSTBITS
LEA DSTPIX(A6),A2 ;USE DSTPIX IN ITS PLACE
_BitsToPix ;CONVERT BITMAP
MOVE.L D1,REALBOUNDS(A6) ;SAVE REAL DST BOUNDS.TOPLEFT
MOVE.B D2,CRSRFLAG(A6) ;REMEMBER IF DST IS SCREEN <BAL 18Sep88>
;----------------------------------------------------
;
; CONVERT PIXEL DEPTH TO SHIFT AMOUNT TO AVOID MULTIPLIES
;
leaROM ciSHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE DSTPIX+PIXELSIZE(A6),D0 ;GET DST PIXEL SIZE
MOVEQ #0,D1 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D0),D1 ;GET SRC SHIFT
MOVE D1,DSTSHIFT(A6) ;AND SAVE DST SHIFT AMOUNT
;----------------------------------------------------------------
;
; SET UP NEWPATTERN TO INDICATE OLD OR NEW STYLE PATTERN
; ALSO SET UP LOCAL PATTERN POINTER, LOCPAT(A6)
;
LEA PNPAT(A3),A0 ;POINT TO THE PATTERN
MOVE.L A0,LOCPAT(A6) ;COPY PATTERN POINTER
MOVE LOCMODE(A6),D0 ;get requested mode
jmpROM ciDrawLine
GOHOME jmpROM ciGOHOME
;-------------------------------------------------------
;
; SET UP AND DRAW A FAST HORIZONTAL OR VERTICAL LINE.
;
FASTLINE
ciDONE EQU $29E66
ciDOONE EQU $29F02
ciDOEND EQU $29F0A
ciALLONE EQU $29F20
ciVLINE EQU $29F72
ciHVSETUP EQU $29FE0
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
moveq #true32b,d0 ;switch to 32 bit addressing
move.w d1,-(sp) ;save a register
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.w (sp)+,d1 ;restore d1
move.b d0,MMUsave(a6) ;save previous state for later
MOVE.L alphaMask(A6),D4 ;get alpha mask
CMP D1,D3 ;IS LINE HORIZONTAL ?
BNE VLINE ;NO, MUST BE VERTICAL
jsrROM ciHVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL
MOVEQ #-1,D6 ;GET ONES IN D6
LSR.L D0,D6 ;CONVERT TO LEFTMASK
MOVE MINRECT+RIGHT(A6),D2 ;GET MINRECT RIGHT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT TO GLOBAL
EXT.L D2 ;MAKE IT LONG
LSL.L D3,D2 ;CONVERT PIXELS TO BITS
MOVEQ #$1F,D0 ;NEED RIGHT MOD 32
AND.L D2,D0 ;MAKE A COPY OF RIGHT
MOVEQ #-1,D3 ;GET ONES IN D3
LSR.L D0,D3 ;SHIFT IN 0'S FOR LEFTMASK
NOT.L D3 ;CONVERT TO RIGHTMASK
AND.L D4,D6 ;
AND.L D4,D3 ;
LSR.L #5,D2 ;CONVERT BITS TO LONGS
CMP #1,LOCMODE(A6) ;WHICH MODIFIED MODE ?
BLT.S HSET ;BR IF FOREGROUND
BEQ.S HTOGL ;BR IF XOR
;ELSE BACKGROUND
;------------------------------------------------------
;
; DRAW A HORIZONTAL LINE IN THE BACKGROUND COLOR (NORMALLY WHITE)
;
MOVE.L BCOLOR(A6),D5 ;GET THE COLOR
BRA.S HDRAW
;--------------------------------------------
;
; DRAW A HORIZONTAL LINE IN THE FOREGROUND COLOR (NORMALLY BLACK)
;
HSET MOVE.L FCOLOR(A6),D5 ;GET THE FOREGROUND COLOR
HDRAW SUB D1,D2 ;CALC LONG COUNT
BEQ.S ALLONE ;BR IF ALL IN ONE LONG
MOVE.L D5,D1 ;COPY COLOR
AND.L D6,D1 ;MASK COLOR FOR LEFT EDGE
NOT.L D6 ;GET NOT LEFTMASK
AND.L (A4),D6 ;PUNCH HOLE IN DEST
OR.L D1,D6 ;COMBINE SRC AND DST
MOVE.L D6,(A4)+ ;AND DROP COLOR IN
SUB #1,D2 ;DEC LONG COUNT
BEQ.S DOEND ;BR IF NO UNMASKED LONG
NOT.L D4
BEQ.S DOONE
ALPHALINE
MOVE.L (A4),D0
EOR.L D5,D0
AND.L D4,D0
EOR.L D5,D0
MOVE.L D0,(A4)+
DBRA D2,ALPHALINE
DOEND jmpROM ciDOEND
DOONE jmpROM ciDOONE
ALLONE jmpROM ciALLONE
ALIGN Alignment
;--------------------------------------------------
;
; DRAW AN XOR HORIZONTAL LINE
;
HTOGL SUB D1,D2 ;CALC LONGCOUNT
BEQ.S ONETOGL ;BR IF ALL IN ONE LONG
EOR.L D6,(A4)+ ;DO LEFT LONG WITH MASK
SUB #1,D2 ;DEC LONG COUNT
BEQ.S ENDTOGL ;BR IF NO UNMASKED LONGS
BRA.S TOGLONE ;SEE IF ANY LONGS LEFT TO DO
TOGLTWO EOR.L D4,(A4)+ ;INVERT A LONG
TOGLONE EOR.L D4,(A4)+ ;INVERT ANOTHER LONG
SUB #2,D2 ;ANY UNMASKED LONGS LEFT ?
TOGLMORE BGT TOGLTWO ;YES, AT LEAST TWO LONGS
BEQ TOGLONE ;YES, FINISH UP LAST LONG
ENDTOGL EOR.L D3,(A4) ;DRAW LINE
BRA.S DONE ;RESTORE CURSOR AND QUIT
ONETOGL AND.L D3,D6 ;COMBINE LEFT AND RIGHT MASK
EOR.L D6,(A4) ;DRAW LINE
DONE jmpROM ciDONE ;RESTORE CURSOR AND QUIT
;-------------------------------------------------------
;
; DRAW A ONE PIXEL WIDE VERTICAL LINE.
;
VLINE jsrROM ciHVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL
MOVEQ #-1,D2 ;GET ONES IN D2
LSR.L D0,D2 ;CONVERT TO LEFTMASK (LEFT MOD 32 IN D0)
MOVE.L D2,D0 ;GET LEFTMASK
MOVE DSTPIX+PIXELSIZE(A6),D1 ;GET PIXEL SIZE
LSR.L D1,D0 ;SHIFT BY PIXEL SIZE FOR RIGHT EDGE
NOT.L D0 ;MAKE IT A RIGHTMASK
AND.L D0,D2 ;AND RIGHTMASK INTO LEFTMASK
AND.L D4,D2
jmpROM ciVLINE
FASTSLANT
ciFASTSLANT EQU $2A080
ciGOBACK EQU $2A410
TST.B alphaMode(A6) ;if alphamode != 0, use slower code
;The logic here is different than
BEQ.S @stay ; RAM based version to avoid patching
@goBack jmpROM ciGOBACK ; out a bunch of code to speed up
@stay jmpROM ciFASTSLANT ; two marginal line drawing cases.
;Patches from GWorlds.a
;RectRgn PROC EXPORT
; cmpRA FromROMNewGWorld,(SP)
; BEQ.S @1
; ADDQ #4,SP
; peaROM ciSkipGVarStuff
; @1: jmpROM ciRectRgn
; Store museDevice (which is the offscreen device or aGDevice or the deepest
; device intersecting boundsRect) in the grafVars.
; move.l offscreenPort(a6),a0 ; get pointer to offscreen port
; move.l ([grafVars,a0]),a0 ; get pointer to grafVars structure
; move.l museDevice(a6),attachDevice(a0) ; store museDevice in grafVars
;=========================================================================================
;=========================================================================================
;
; INSTALLS HERE
;
;=========================================================================================
;=========================================================================================
CutBackPt PROC EXPORT
EXPORT InitPatches
EntryTable CopyPixPat,$AA09 ; comefrom to fix direct pixpats in pictures <KON 4FEB90>
if not(TheFuture) then ; <124> Need this for the present
EntryTable CalcMask,$A838 ; CalcMask and SeedFill need to <KON 24JAN91>
EntryTable SeedFill,$A839 ; always scan up as well as down <KON 24JAN91>
endif ; <124>
EntryTable slHilite,$AB90 ; Fix hilite slabbing of pixpats <85>
EntryTable RAMslArith16Tab,$ABBD ; Fix hilite slabbing of pixpats <85>
EntryTable RAMslArith32Tab,$ABBE ; Fix hilite slabbing of pixpats <85>
EntryTable RectRgn,$A8DF ; Fixes of alpha channel crimes
EntryTable DrawLine,$AB0A ;
EntryTable FastSlabMode,$AB0C ;
if not(TheFuture) then
EntryTable PatExpand,$AB15 ;
endif
EntryTable PushVerb,$AB18 ;
EntryTable bSETUP8,$AB34 ;
EntryTable bXMAIN8,$AB38 ;
EntryTable bLONG8,$AB44 ;
EntryTable bXLONG8,$AB48 ;
EntryTable rMASK8,$AB5E ;
EntryTable FastLine,$AB9C ;
EntryTable FastSlant,$AB9D ;
EntryTable AlphaDispatch,$ABC0 ;
EntryTable StreamToMask,$ABC1 ;
EntryTable stArith16Tab, $ABA6 ;Patch 16-bit arithmetic loops to end in RTS
EntryTable stArith32Tab, $ABA7 ;Patch 32-bit arithmetic loops to end in RTS
EntryTable StdRect, $A8A0 ;Patch all these so OpenCPicture
EntryTable StdLine, $A890 ;works in GrafPorts. The problem
EntryTable StdRRect, $A8AF ;is Update pat is not vectored and
EntryTable StdOval, $A8B6 ;it is called by PutPicVerb which
EntryTable StdArc, $A8BD ;is called by all the std procs.
EntryTable StdRgn, $A8D1 ;You're lucky you didn't have to do
EntryTable StdPoly, $A8C5 ;this.
EntryTable SlabMode,$AB25 ;set up patterns for 16 and 32-bit dests
EntryTable rTransparent,$AB6A ;new transparent rgn-clipped blit loop
EntryTable bTransparent,$AB54 ;new transparent rect-clipped blit loop
EntryTable RAMbArith16Tab,$ABB8 ;bArith16Tab move to RAM to fix subOver16
EntryTable bSloHilite,$AB4E ; Make it use background color correctly
EntryTable rXMASK8,$AB62 ; new big pattern rgnblit copy loop
EntryTable rSlowHilite,$AB70 ; new hilite pattern blit loop
EntryTable RgnBlt,$AB1F ; to make hilite patterns work
if not(TheFuture) then ; <124> Need this for the present
EntryTable GetPixel,$A865 ; make it work with pmVersion 4 pixmaps
EntryTable GetCPixel,$AA17 ; make it work with pmVersion 4 pixmaps
endif ; <124>
EntryTable KopyMask,$AA51 ; new trap: copyMask with mode and rgn
EntryTable OpenCPicture,$AA20 ; Add handle for font name list
EntryTable OpenPicture,$A8F3 ; Add new trap
if not(TheFuture) then ; <124> Need this for the present
EntryTable ClosePicture,$A8F4 ; Dispose of font name list handle
endif ; <124>
EntryTable DrawPicture,$A8F6 ; Support font name/ID binding on playback
EntryTable PicItem1, $AB9A ; font name/ID binding support
EntryTable StdOpcodeProc, $ABF8 ;hres, vres support to picFrames
EntryTable PatConvert, $AB13 ;fix pixpat expansion bug
EntryTable GetCIcon, $AA1E ;size = height * rowbytes (not *pixdepth)
EntryTable QDExtDispatcher, $AB1D ;added selectors 22 and 23 and patch UpdateGWorld
;
; UpdateGWorld patched to OR.L rather than MOVE.L StretchPixMask into the result
;
EntryTable InitPort, $A86D ;added support for moving base adr.
EntryTable OpenPort, $A86F ;added support for moving base adr.
EntryTable InitGDevice, $AA2E ;moving base adr support
EntryTable BitsToPix, $AB02 ;moving base adr support
EntryTable SetupStretch, $AB24 ;come from patch to add index to index dithering
;
; Completely replace stretch
;
EntryTable StretchBits, $AB27 ;complete stretch replacement
EntryTable BlitCase, $AB98 ;complete stretch replacement
EntryTable StScanLoop, $AB99 ;complete stretch replacement
EntryTable stMask0, $AB73 ;do colorizing only when needed
EntryTable ColorMap, $AB04 ;patched for colorizing in color space
EntryTable MakeScaleTbl, $AB0E ;pin to pixdepth entries, add color space colorizing
EntryTable RAMstColorTab, $ABA8 ;stColorTab moved to RAM to support fix dither bug
EntryTable RAMscDirTab8, $ABB5 ;scDirTab moved to RAM to support fix dither bug
EntryTable RAMstGrayTab, $ABA9 ;stGrayTab moved to RAM for Dither
EntryTable RAMstSearchTab, $ABAA ;stSearchTab moved to RAM for Speedup of 32 and 16 to ind.
EntryTable StdBits, $A8EB ;clear dither bit when recording old pict.
EntryTable Index2Color, $AA34 ;Calc color the same as Search16toIndexed.
EntryTable ScrollRect, $A8EF ;Set update region when scrolling between diff. res. dev.
; EntryTable RecoverHandle, $A028 ;also recover handles in MFZone
EntryTable BitsDevLoop, $AB9E ;remove references to BaseAddr
EntryTable GetSeek, $AB0D ;come-from lines, arcs, poly for wide rowbytes
EntryTable FastSlabMode, $AB0C ;come-from lines, arcs, poly for wide rowbytes
EntryTable stNoStack, $AB97 ;Try for 128K instead of 64K
EntryTable MakeITable, $AA39 ;save theZone across calls
EntryTable DisposeTempBuffer, $AB1E ;comefrom MakeITable patch to clean up temp handles
EntryTable InvertColor, $AA35 ;Address of color for comp procs was not correct.
;
; patched below
;
; EntryTable StdTxMeas, $A8ED ;comefrom GetRect patch to multiply by size by h scaling
; EntryTable GetMaxDevicePatch,$AA27 ; new trap: copyMask with mode and rgn
;
; Quicker Draw Patches
;
EntryTable slAddOver8,$AB8A
EntryTable slSubOver8,$AB8E
EntryTable slAddPin8,$AB89
EntryTable slSubPin8,$AB8B
EntryTable slMax8,$AB8D
EntryTable slMin8,$AB8F
EntryTable slAvg8,$AB88
EntryTable slTransparent8,$AB8C
EntryTable rAddOver8,$AB68
EntryTable rSubOver8,$AB6C
EntryTable rAddPin8,$AB67
EntryTable rSubPin8,$AB69
EntryTable rMax8,$AB6B
EntryTable rMin8,$AB6D
EntryTable rAvg8,$AB66
; EntryTable rTransparent8,$AB6A ;<SMC 08OCT90> <72>
EntryTable bAddOver8,$AB52
EntryTable bSubOver8,$AB56
EntryTable bAddPin8,$AB51
EntryTable bSubPin8,$AB53
EntryTable bMax8,$AB55
EntryTable bMin8,$AB57
EntryTable bAvg8,$AB50
; EntryTable bTransparent8,$AB54 ;<SMC 08OCT90> <72>
EntryTable FillClipScanLine, $AB80 ;More Quickerdraw stuff <27FEB90 KON>
EntryTable FillClipOrLine, $AB81
EntryTable FillClipXLine, $AB84
EntryTable 0
InitPatches
Import FixupTbl ; added FixupTbl
;____________________________________________________________________________
; Fixup patch addresses
;
; The Fixing up of addresses generated by the CMPRA, JSRROM & JMPROM
; Breaks down as follows:
;
; Addressing High Byte in Action
; mode: instruction:
; ---------- ------------ ------
; 24 bit NZ Do not alter the address in the instruction.
; Used with CMPRA to a ROM Resource.
; 32 bit NZ Mask out 12 high bits from the address
; in the instruction, leaving a ROM offset
; Then add in ROMBase.
; either Zero Normal Case. Add ROMBase to the address
; in the instruction.
;
; Registers:
; D0: Address Size Flag. Pos: 24 bit mode; Neg: 32 bit Mode
; D1: Entry from table of offsets of locations to be fixed up
; D2: (RomBase)
; A0: Pointer into table of offsets of locations to be fixed up.
; A1: Base of fixup table; also location from which offsets are computed.
if not(TheFuture) then ; <124> OId equate for now
GetPMData EQU $40833610 ; <124>
endif ; <124>
if TheFuture then ; <124> New equate for TheFuture
GetPMData EQU $33610
endif ; <124>
; EntryTable GetPMData, $ABC4 ;install as a trap
if not(TheFuture) then ; <124> Old code for now
move.l #GetPMData,a0 ; <124>
endif ; <124>
if TheFuture then ; <124> New code for TheFuture
move.l rombase,a0
add.l #GetPMData,a0
endif ; <124>
move #$ABC4,d0
_SetTrapAddress ,NEWTOOL
; EntryTable DelSearch,$AA4C ; call xlate24to32 on address
; EntryTable DelComp,$AA4D ; call xlate24to32 on address
;
; Only install DelSearch and DelComp if our return address is what we are expecting
; This hack is necessary since DelSearch and DelComp routines in the Erickson ROM
; are already patched! Thanx!
;
ciDelCompEntryValue EQU $2270
ciDelCompEntry EQU $3CAC4
move.l #ciDelCompEntry,a0
add.l ROMBase,a0
cmp.w #ciDelCompEntryValue,(a0)
lea DelSearch,a0
bne.s @Erickson
move #$AA4C,d0
_SetTrapAddress ,NEWTOOL
lea DelComp,a0
move #$AA4D,d0
_SetTrapAddress ,NEWTOOL
@Erickson
;
; Move stColorTab to RAM ;<SMC 27SEP90> <69>
;
MOVE.W #$ABA8,D0
MOVEQ #-120,D1 ;MOVEQ #%10001000,D1 (stupid assembler)
LEA RAMstColorTab,A1
BSR TabPatcher8
;
; Move scDirTab8 to RAM ;<SMC 27SEP90> <69>
;
MOVE.W #$ABB5,D0
MOVEQ #%00100000,D1 ;assembles because high bit is clear
LEA RAMscDirTab8,A1
BSR TabPatcher8
;
; Move stGrayTab to RAM ;<SMC 27SEP90> <69>
;
MOVE.W #$ABA9,D0
MOVEQ #-52,D1 ;MOVEQ #%11001100,D1 (again, stupid assembler)
LEA RAMstGrayTab,A1
BSR TabPatcher8
;
; Move bArith16Tab to RAM ;<SMC 08OCT90> <71>
;
MOVE.W #$ABB8,D0
MOVEQ #%001000000,D1
LEA RAMbArith16Tab,A1
MOVEQ #8,D2 ;9 entries
BSR TabPatcher
;
; Move slArith16Tab to RAM ;<85>
;
MOVE.W #$ABBD,D0
MOVE.L #%100000000,D1
LEA RAMslArith16Tab,A1
MOVEQ #8,D2 ;9 entries
BSR TabPatcher
;
; Move slArith32Tab to RAM ;<85>
;
MOVE.W #$ABBE,D0
MOVE.L #%100000000,D1
LEA RAMslArith32Tab,A1
MOVEQ #8,D2 ;9 entries
BSR TabPatcher
;
; (stSearchTab is now patched out entirely to RAM)
;
;-------------------------------------------------------------------------------
;
; Routine patches Traps $AB75 - $AB7F to end with an RTS
;
; The routine is moved into RAM and then the RTS is added and the
; new trap address is set
;
move.w #$AB74,d0
_GetTrapAddress ,newTool
move.l a0,a1 ;copy source address
;
; Get newptr to copy trap into
;
RtnSize EQU $37D98-$37A20 ;$379F0 ($AB73) ; End of $AB7F - beginning of $AB74
move.l #RtnSize, d0 ;
_NewPtr ,SYS
move.l a0,a2 ;save beginning of 1st routine
suba.l a1,a2
move.w #$AB74,d0
_SetTrapAddress ,NewTool ;set address of first trap
;
; Check for errors?
;
move.w #(RtnSize/4)-1, d2 ; long count of routine size
@Loop
move.l (a1)+,(a0)+ ;move all the code over
dbra d2, @Loop
;
; Now change all the BRA's at the end of the routines to RTS's by looking backward
; for a $6000
;
move.w #$AB75,d2 ;first routine ends
@Loop1
move.w d2,d0
_GetTrapAddress ,newTool
;
; Patch up the Trap addresses while we're here
;
move.w d2,d0
adda.l a2,a0
move.l a0,a1
_SetTrapAddress ,NewTool
@Loop2
cmp.w #$6000,-(a1)
bne.s @Loop2
move.w #$4E75, (a1)
addq.w #1,d2
cmp.w #$AB80,d2
bne.s @Loop1
;
; Trap AB7B has two hard branches we need to replace, so search backwards for
; the one we missed.
;
@Special
cmp.w #$6000,-(a1)
bne.s @Special
move.w #$4E75, (a1)
;
; To handle the last one, search forward for $6000
;
@Loop3
cmp.w #$6000,(a1)+ ;This was done by a dark skinned man....
bne.s @Loop3
move.w #$4E75, -2(a1)
; _Debugger
move.l RomBase, D2
moveq #-1, D0
_StripAddress
lea FixupTbl, A0
move.l A0, A1
FixUpLooP move.l (A0)+, D1
beq.s @1
tst.b 0(A1, D1.L)
beq.s @AddIt
tst.l D0 ; If Address has any high bits set
bpl.s FixUpLoop ; 24 Bit mode; Dont alter this one.
and.w #$f, 0(A1, D1.L); 32 Bit Mode; Clear High 12 bits.
@AddIt add.l D2, 0(A1, D1.L) ; Normal Case: Add in ROMBase
bra.s FixUpLoop
@1
MOVE.W HwCfgFlags,D0 ; check em the compulsive way
BTST #hwCbAUX,D0 ; is it A/UX time?
BNE.S @NoNewCursor ; if so, skip crsr installs
lea PatchJShowCursor,a0
move.l a0,JShowCursor
lea PatchJSetCCursor,a0
move.l a0,JSetCCrsr
@NoNewCursor
PatchToolJump oldDisposGDevice,$230 ;If gDevice = lastTxDevice, move mainGdevice to lastTxDev
InstToolTp newDisposGDevice,$230
PatchToolJump oldMapRgn,$0FB ;check for wide open rectangular regions
InstToolTp newMapRgn,$0FB
leaFar CutBackPt,a0 ; ptchInstall will cut back to here
; and install the traps in the table.
rts
;---------------------------------------------------------
; <SMC 27SEP90> <69>
;
; TabPatcher - patch specific entries in a vectorized
; blit-loop offset table.
;
; D0 = table trap number
; D1 = bitmask
; D2 = entries count (zero based)
; A1 = RAM table address
;
; The lowest bit of the of the bitmask corresponds to the
; first entry in the table, and so on. If a bit in the mask
; is one, the proc is in RAM so leave the entry alone in the
; new table. If a bit is zero, the entry is still in ROM so
; adjust the offset in the new table to be the distance between
; it and the ROM proc.
;
TabPatcher8 MOVEQ #7,D2
TabPatcher MOVE.L D3,-(SP)
_GetTrapAddress ,newTool
MOVE.L A0,D0
SUB.L A1,D0
@1: MOVE.L (A0)+,D3
LSR.L #1,D1
BCS.S @2
ADD.L D0,D3
MOVE.L D3,(A1)
@2: ADDQ #4,A1
DBRA D2,@1
MOVE.L (SP)+,D3
RTS
endproc
Proc
Export FixupTbl
;################## TABLE OF LOCATIONS TO BE OFFSET BY [ROMBase] ####################
;
; Table contains one entry for each reference to a ROM address from the
; JmpROM, JsrROM, and CmpRA macros. &RomFixIndex is a count of the total
; number of these references, and is also used to synthesize the label
; names for them. The reference labels have the form
; RXXX000, RXXX001, RXXX002, ...
; See the Macro definitions for JmpROM, JsrROM and CmpRA (near the top of
; this file) for more info.
;
; MkTbl is a macro only because assembler while loops will not work
; outside of macros.
;
MACRO
MkTbl
gbla &RomFixIndex
while &RomFixIndex <> 0 do
&RomFIxIndex seta &RomFixIndex - 1
dc.l RXXX&I2S(&ROMFIXINDEX,-3) - FixUpTbl
endwhile
dc.l 0 ; Zero entry marks end of table
ENDM
FixupTbl MkTbl
;########################### END PATCHES CUT BACK CODE ################################
endproc
end