; ; 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): ; ; 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 : 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, yÕbroke 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 wasnÕt.) Give the If a Then to ; keep it company. ; <119> 9/13/91 DTY DonÕt 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 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 KonstantinÕs fault, really. My initials were on it, but ; I really didnÕt 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 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 ; bra.s FirstPass ;search up and down ;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, donÕt clear the invert bit BCLR #4,D2 ;hilite? BEQ.S @skipHilite ;if not, donÕt 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 havenÕt 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. ; <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 <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 ext.l d1 ;clear out high word lsl.l d4,d1 ;convert to bits subq.l #1,d1 ;force downward round LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 LSR #5,D0 ;get (pixels in scanbuf)/32 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 ;----------------------------------------------------------------------- ; ; 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, canÕt 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 MOVE D6,D5 ;get vert pattern offset ADD.L D5,A0 ;BUMP TO PROPER ROW 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 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 ; clr.b CrsrObscure ;unobscure cursor if level went past zero ;fall into DrawCursor ;________________________________________________________________________ ; DrawCursor is much like ShowCursor, but doesn't increment the CrsrState 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 ? BLT.S NXTDEV ;=>YES, CHECK NEXT DEVICE CMP (A1)+,D5 ;IS HORIZONTAL < GDRECT.LEFT ? BLT.S NXTDEV ;=>YES, CHECK NEXT DEVICE 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 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 ; baseAddr32Bit EQU 2 tst.w rowbytes(a3) ; bpl.s MMUModeOK ;it's a bitmap btst #baseAddr32Bit,pmVersion+1(a3) ; bne.s Needs32BitMode ;pixmap needs 32-bit addressing 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) 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 ; DAF ciDelCompEntry EQU $3CAF4 MOVE.L 4(SP),D0 ; get the CompProc pointer _rTranslate24To32 ; clean up the address move.l d0,d1 ; put proc pointer where the ROM expects it jmpROM ciDelCompEntry ENDPROC DelSearch PROC EXPORT ; DAF ciDelSearchEntry EQU $3CAC4 MOVE.L 4(SP),D0 ; get the SearchProc pointer _rTranslate24To32 ; clean up the address 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 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 DAF MOVE.L D0,A0 ; set up to lock this element DAF _HLock ; lock it down so that A2 will be valid after the JSR 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 DAF ; MOVE.L CompProc(A0),A0 ; get the complement proc ptr DAF ; JSR (A0) ; execute routine ; MOVE.L A2,A0 ; set up for HUnlock DAF ; _HUnlock ; release the compElement DAF ; TST.B (SP)+ ; test the result ; BNE.S FoundComp ; if result = TRUE then quit ; MOVE.L (A2),A0 ; get the compElement pointer again DAF ; MOVE.L NxtComp(A0),D0 ; get pointer to next DAF ; BRA.S @1 ; ;FoundComp ; MOVE.L (SP)+,A2 ; restore the register 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 DAF MOVE res(A6),D7 ; get the channel size EHB CMP.L #-1,theGDevice ; if -1, then it's uninitialized DAF BEQ.S @ResCheck ; OK, so continue DAF @GDevOK MOVE.L ([theGDevice]),A0 ; get a pointer to the current device DAF ; test the parameters. If ITabH or CTabH are NIL, substitute handles from theGDevice DAF TST.L ITabH(A6) ; is ITabH NIL? DAF BNE.S @DoCTabH ; no, so continue DAF MOVE.L GDITable(A0),ITabH(A6) ; stick theGDevice's ITabH in stack frame DAF @DoCTabH TST.L CTabH(A6) ; is CTabH NIL? DAF BNE.S @DoITabRes ; no, so continue DAF MOVE.L ([GDPMap,A0]),A1 ; get pixMap's handle DAF MOVE.L PMTable(A1),CTabH(A6) ; get the device colorTable's pointer DAF @DoITabRes ; get the ITable resolution TST D7 ; test the channel size EHB BNE.S @ResCheck ; if valid, continue DAF ; the res parameter was 0, so get theGDevice's preferred resolution DAF MOVE.W GDResPref(A0),D7 ; get the preferred ITabRes DAF BNE.S @ResSubst ; if non-zero, then continue DAF MOVEQ #4,D7 ; if resPref=0, then force to 4 DAF @ResSubst MOVE.W D7,res(A6) ; and put it in the stack frame DAF @ResCheck CMP.W #2,D7 ; don't accept res²2 DAF BLE.S @BadRes ; DAF CMP.W #6,D7 ; or ³ 6 DAF BLT.S @ResOK ; DAF @BadRes MOVE.W #cResErr,QDErr ; mark the error and quit DAF BRA MITDone ; DAF @ResOK ; DAF ; Calculate the size of the compressed table and verify the handle MOVE D7,D1 ; get the channel size 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? DAF BEQ.S @1 ; yes, so Realloc it DAF _SetHandleSize ; set the size DAF BRA.S @2 ; and continue DAF @1 _ReallocHandle ; DAF @2 BEQ.S @SizeOK ; => size ok, so continue DAF MOVE.W #CNoMemErr,QDErr ; report this error DAF BRA MITDone ; and quit DAF @SizeOK ;--------------------------------------------------------------------- ; ; 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 ;--------------------------------------------------------------------- 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 DAF MOVE.L #'mitq',-(SP) ; push the queue size resource type DAF CLR.W -(SP) ; want mitq=0 DAF _rGetResource ; system first, then ROM DAF MOVE.L (SP)+,A0 ; get the handle DAF MOVE.L (A0),A0 ; get the pointer in A0 DAF MOVE.L -12(A0,D7*4),D0 ; get the queue size (adjust for no 1 or 2 bit resolutions) 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 ; DAF ; MOVE.L SvZone(A6),theZone ; always restore the zone (needed for error exits) MOVEM.L (SP)+,A2-A5/D3-D7 ; restore registers UNLK A6 ; bag the stack frame RTD #ParamSize ; flush parameters and return home 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 ; 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 ; 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 ; move.l d0,stackFree(a6) ; 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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 _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 _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 _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 _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 _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 _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 _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 _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 move.l sp,-(sp) ;point to this record _SaveFore sub.l #ColorSpecSize,sp ;make room for an ColorSpec 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 ; move.l DeviceList,a0 ;get the head of the device list 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 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 ; 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 DAF MOVE.L 4(SP),A0 ; get pointer to result RGB 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? beq.s I2CDirect ; yes, no CLUT 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 DAF CMP.W D1,D0 ; is index in range? DAF BGT.S I2CErr ; nope, so quit DAF MOVE.W CTTable+rgb+red(A1,D0.L*8),red(A0) ; move red DAF MOVE.L CTTable+rgb+green(A1,D0.L*8),green(A0) ; move green & blue DAF I2CDone RTD #8 ; and return I2CErr MOVE.W #cRangeErr,QDErr ; set error code BRA.S I2CDone ; I2CDirect ; Handle 24bit/pixel direct devices 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 ;---------------------------------------------------- ; ; 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? Bne.s doScreen ;Yes, convert it tst.b d6 ;is source a bitmap? bne notScrn ;YES, don't convert tst.b OldPic(a6) ;is dst old port? beq notScrn ;No, then don't convert source bra doConvert doScreen IF 1 THEN ;Can't optimize if screen needs 32-bit addressing ; ;---------------------------------------------------- ; 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? 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. 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 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 move.l d0,theGDevice ;set up offscreen GDevice 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 ;---------------------------------------------------- ; ; 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? 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? beq.s @NoDither ; move.w #$40,(sp) ;set dither mode @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 ;---------------------------------------------------- ; ; 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 ;---------------------------------------------------- ; ; 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 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? beq.s @PackOK ;no, don't need to adjust packType CMP #16,SRCPIX+PIXELSIZE(A6) ;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 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> move.l d0, -(SP) ;PUSH CTABHANDLE <20> 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. ; 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 move #MinTableSize,-(sp) ;GET SIZE IN ENTRIES jsrROM PutPicData ;ADD TO THEPIC 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 move.w pmVersion(a6),-(sp) ;save pmVersion move.l a1,-(sp) ;PutPMData trashes A1 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 ; 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 move.w (sp)+,pmVersion(a6) ;restore pmVersion move.w (sp)+,packtype(a1) ;restore packtype 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 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 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 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) ; ; <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. ; ; tst.b d5 ;are both src and destination the screen? beq.s @cont ;=>NO, Don't check for overlap <104> cmp.l SRCDEVICE,d1 ;are src and destination the same device? 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 ; ; 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 sub.w d0,d7 ; get luminance error as a word ENDM ;------------------------------------------------------------------ ; ; SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED ; ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB' ; ; USES: D3: SRC PIXEL SIZE ; D4: DST PIXEL SIZE ; A0: SRC BUFFER ; A1: DST BUFFER ; A2: END OF DST BUFFER ; A4: PIXEL TRANSLATE TABLE ; ; CLOBBERS A0-A1/D0-D5 ; MOVEM.L D6/D7,-(SP) ;SAVE WORK REGISTERS @1 MOVE.L ErrBuf(a6),A4 ;get ptr to ErrBuf MOVEQ #0,D5 ;INIT OFFSET INTO DST MOVE.L D5,D0 ;clear high end MOVE.L D5,D1 ;clear high end MOVE.L D5,D2 ;clear high end not.b errDir(a6) ;check and toggle diffusion direction bne.s @forward move.l ErrSrcBuf(a6),a0 ;point to end of srcBuf moveq #32,d5 ;init dst offset in long @back2 sub.w D4,D5 ;pre-BUMP TO NEXT DST PIXEL @backward sub.w #2,a4 MOVE.L -(A0),D3 ;GET NEXT LONG OF SRC _DitherBitmap32 asr.w #1,d7 ;get half error (signed) move.w d7,(a4) ;save 1/2 for next scanline and carry 1/2 to right sub.w D4,D5 ;BUMP TO NEXT DST PIXEL bge.s @backward ;TIME FOR NEXT DST LONG? =>NO moveq #32,d5 MOVE.L D6,-(A2) ;ELSE SAVE CURRENT LONG CMP.L A2,A1 ;DSTPTR >= DSTLIMIT? BLO.S @back2 ;if lower, continue to next pixel move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion bra.s @donescl @forward MOVE.L (A0)+,D3 ;GET NEXT LONG OF SRC _DitherBitmap32 asr.w #1,d7 ;get half error (signed) move.w d7,(a4)+ ;save 1/2 for next scanline and carry 1/2 to right ADD D4,D5 ;BUMP TO NEXT DST PIXEL AND #$1F,D5 ;TIME FOR NEXT DST LONG? BNE.S @forward ;=>NO MOVE.L D6,(A1)+ ;ELSE SAVE CURRENT LONG CMP.L A2,A1 ;DSTPTR >= DSTLIMIT? BLO.S @forward ;if lower, continue to next pixel move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion move.l a0,ErrSrcBuf(a6) ;point to end of srcBuf for right to left diffusion @DONESCL MOVEM.L (SP)+,D6/D7 ;RESTORE WORK REGISTERS RTS ENDPROC ;========================================================================================= ;========================================================================================= ; ; 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 sub.w d0,d7 ; get luminance error as a word ENDM ;------------------------------------------------------------------ ; ; SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED ; ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB' ; ; USES: D3: SRC PIXEL SIZE ; D4: DST PIXEL SIZE ; A0: SRC BUFFER ; A1: DST BUFFER ; A2: END OF DST BUFFER ; A4: PIXEL TRANSLATE TABLE ; ; CLOBBERS A0-A1/D0-D5 ; MOVEM.L D6/D7,-(SP) ;SAVE WORK REGISTERS moveq #0,d3 ;clear out high word @1 MOVE.L ErrBuf(a6),A4 ;get ptr to ErrBuf MOVEQ #0,D5 ;INIT OFFSET INTO DST MOVE.L D5,D0 ;clear high end MOVE.L D5,D1 ;clear high end MOVE.L D5,D2 ;clear high end not.b errDir(a6) ;check and toggle diffusion direction bne.s @forward move.l ErrSrcBuf(a6),a0 ;point to end of srcBuf moveq #32,d5 ;init dst offset in long @back2 sub.w D4,D5 ;pre-BUMP TO NEXT DST PIXEL @backward sub.w #2,a4 MOVE.w -(A0),D3 ;GET NEXT LONG OF SRC _DitherBitmap16 asr.w #1,d7 ;get half error (signed) move.w d7,(a4) ;save 1/2 for next scanline and carry 1/2 to right sub.w D4,D5 ;BUMP TO NEXT DST PIXEL bge.s @backward ;TIME FOR NEXT DST LONG? =>NO moveq #32,d5 MOVE.L D6,-(A2) ;ELSE SAVE CURRENT LONG CMP.L A2,A1 ;DSTPTR >= DSTLIMIT? BLO.S @back2 ;if lower, continue to next pixel move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion bra.s @donescl @forward MOVE.w (A0)+,D3 ;GET NEXT LONG OF SRC _DitherBitmap16 asr.w #1,d7 ;get half error (signed) move.w d7,(a4)+ ;save 1/2 for next scanline and carry 1/2 to right ADD D4,D5 ;BUMP TO NEXT DST PIXEL AND #$1F,D5 ;TIME FOR NEXT DST LONG? BNE.S @forward ;=>NO MOVE.L D6,(A1)+ ;ELSE SAVE CURRENT LONG CMP.L A2,A1 ;DSTPTR >= DSTLIMIT? BLO.S @forward ;if lower, continue to next pixel move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion move.l a0,ErrSrcBuf(a6) ;point to end of srcBuf for right to left diffusion @DONESCL MOVEM.L (SP)+,D6/D7 ;RESTORE WORK REGISTERS RTS ENDPROC ;========================================================================================= ;========================================================================================= ; ; 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 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 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 move.b (a5,d1),d1 ; get actual luminance as a word sub.w d1,d7 ; get luminance error as a word ENDM ;------------------------------------------------------------------ ; ; SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO 1-8 BIT INDEXED ; ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB' ; ; USES: D3: SRC PIXEL SIZE ; D4: DST PIXEL SIZE ; A0: SRC BUFFER ; A1: DST BUFFER ; A2: END OF DST BUFFER ; A4: PIXEL TRANSLATE TABLE ; ; CLOBBERS A0-A1/D0-D5 ; MOVEM.L A3/A5/D6/D7,-(SP) ;SAVE WORK REGISTERS MOVE.L stITabInfo(A6),A3 ;get pointer to the luminance table (past header) lea ITabLuma-ITabInfo(a3),a5 ;point to luma table @1 MOVE.L ErrBuf(a6),A4 ;get ptr to ErrBuf MOVEQ #0,D5 ;INIT OFFSET INTO DST MOVE.L D5,D0 ;clear high end MOVE.L D5,D1 ;clear high end MOVE.L D5,D2 ;clear high end not.b errDir(a6) ;check and toggle diffusion direction bne.s @forward move.l ErrSrcBuf(a6),a0 ;point to end of srcBuf moveq #32,d5 ;init dst offset in long @back2 sub.w D4,D5 ;pre-BUMP TO NEXT DST PIXEL @backward sub.w #2,a4 MOVE.L -(A0),D3 ;GET NEXT LONG OF SRC _DitherGray moveq #0,d3 ; <23Feb90 KON> asr.w #1,d7 ;get half error (signed) move.w d7,(a4) ;save 1/2 for next scanline and carry 1/2 to right addx.w d3,d7 ;prevent error from accumulating <23Feb90 KON> sub.w D4,D5 ;BUMP TO NEXT DST PIXEL bge.s @backward ;TIME FOR NEXT DST LONG? =>NO moveq #32,d5 MOVE.L D6,-(A2) ;ELSE SAVE CURRENT LONG CMP.L A2,A1 ;DSTPTR >= DSTLIMIT? BLO.S @back2 ;if lower, continue to next pixel move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion bra.s @donescl @forward MOVE.L (A0)+,D3 ;GET NEXT LONG OF SRC _DitherGray moveq #0,d3 ; <23Feb90 KON> asr.w #1,d7 ;get half error (signed) move.w d7,(a4)+ ;save 1/2 for next scanline and carry 1/2 to right addx.w d3,d7 ;prevent error from accumulating <23Feb90 KON> ADD D4,D5 ;BUMP TO NEXT DST PIXEL AND #$1F,D5 ;TIME FOR NEXT DST LONG? BNE.S @forward ;=>NO MOVE.L D6,(A1)+ ;ELSE SAVE CURRENT LONG CMP.L A2,A1 ;DSTPTR >= DSTLIMIT? BLO.S @forward ;if lower, continue to next pixel move.l a4,ErrBuf(a6) ;point to end of errBuf for right to left diffusion move.l a0,ErrSrcBuf(a6) ;point to end of srcBuf for right to left diffusion @DONESCL MOVEM.L (SP)+,A3/A5/D6/D7 ;RESTORE WORK REGISTERS RTS ENDPROC ;========================================================================================= ;========================================================================================= ; ; 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 move.b (a5,d1),d1 ; get actual luminance as a word sub.w d1,d7 ; get luminance error as a word ENDM ;------------------------------------------------------------------ ; ; SCALES A SCANLINE OF PIXELS FROM 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 DC.L Dither32toGray-stGrayTab ;B 32 to Indexed Dither DC.L Scale16ToBitMap-stGrayTab ;C 16 to BitMap DC.L Scale16toGray-stGrayTab ;D 16 to Indexed DC.L Dither16toBitmap-stGrayTab ;E 16 to (16) ->BitMap Dither DC.L Dither16toGray-stGrayTab ;F 16 to Indexed Dither 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. ; ; 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 ;---------------------------------------------------- ; ; 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 _GetBackColor ;get bg color for colorizing _GetForeColor move.w XLateFlag(a6),d0 ;restore translation flags cmp.w #4,d4 ; 16-Bit? beq.s @Do16Bit ; ; ; Convert RGB colors to 32-bit colors for foreground ; moveq #0,d1 move.b RGBFrColor(a6),d1 ;red swap d1 move.b RGBFrColor+2(a6),d1 ;green lsl #8,d1 move.b RGBFrColor+4(a6),d1 ;blue move.l d1,fcolor(a6) moveq #0,d1 ;do background move.b RGBBgColor(a6),d1 ;red swap d1 move.b RGBBgColor+2(a6),d1 ;green lsl #8,d1 move.b RGBBgColor+4(a6),d1 ;blue move.l d1,bcolor(a6) bra.s @CheckSwapping @Do16Bit ; ; Convert RGB colors to 32-bit colors for background ; moveq #0,d1 move.b RGBFrColor(a6),d1 ;red lsl #5,d1 ; rrrrrrrr00000 move.b RGBFrColor+2(a6),d1 ;green rrrrrgggggggg lsl.l #5,d1 ; rrrrrgggggggg00000 move.b RGBFrColor+4(a6),d1 ;blue rrrrrgggggbbbbbbbb lsr.l #3,d1 ; 000rrrrrgggggbbbbb move.w d1,fcolor(a6) move.w d1,fcolor+2(a6) moveq #0,d1 move.b RGBBgColor(a6),d1 ;red lsl #5,d1 move.b RGBBgColor+2(a6),d1 ;green lsl.l #5,d1 ; move.b RGBBgColor+4(a6),d1 ;blue lsr.l #3,d1 ; move.w d1,bcolor(a6) move.w d1,bcolor+2(a6) @CheckSwapping btst.l #SwapFGBGBit,d0 ;swap fg/bg colors? beq.s swapdone swapfgbk move.l fcolor(a6),d1 ;swap fg/bk color move.l bcolor(a6),fcolor(a6) move.l d1,bcolor(a6) swapdone ;------------------------------------------------------------------------------ ; Check if colorizing is a NOP. If it is, clear the colorize bits. ; There are three cases: ModeCase, ScaleCase, and SrcBuf colorizing ; ; SrcBuf and ScaleCase colorizing is a NOP IF ; ; for 1-bit sources: ; fcolor = $FFFFFFFF and bcolor = 0 ; ; for deep sources: ; RGBFrColor = 0 and RGBBgColor = $00FFFFFF (32-bit) ; or RGBBgColor = $7FFF7FFF (16-bit) ; ; ModeCase colorizing is NOP if bcolor=0 and fcolor=NOPfgColorTable ; ; If ModeCase or ScaleCase colorizing, check for NOP ; btst.l #ColorizeInModeCaseBit,d0 beq @CheckColorizeInSrcBuf ;branch if SrcBuf or ScaleCase colorizing ; ; Do ModeCase NOP check ; move.l bcolor(a6),d1 ;is bg color a NOP ($00000000)? bne @CheckColorizeNOPDone ;bk not a NOP, go slow move.l fcolor(a6),d1 ;is fg color a NOP? lea NOPfgColorTable,a0 cmp.l (a0,d4*4),d1 bne @CheckColorizeNOPDone ;no, it's not a NOP ; ; It's a NOP, clear colorize bits ; and.w #~(ColorizeInModeCase),d0 ;turn off modecase colorizing bra @CheckColorizeNOPDone @CheckColorizeInSrcBuf ; ; Check SrcBuf or ScaleCase colorizing ; ; if src is indexed and destination indexed: ; NOP if fcolor = $FFFFFFFF and bcolor = 0 ; if src is indexed and destination is direct: ; NOP if fcolor = 0 and bcolor = $00FFFFFF (32-bit) ; bcolor = $7FFF7FFF (16-bit) ; ; Get fg and bg color in RGB space if colorizing at srcbuf, since our source is ; still in RGB space at that time. ; ; D3 contains src pixel depth. ; D4 contains dst pixel depth. ; cmp.w #4,d3 ;deep src? bge.s @DeepSrc cmp.w #4,d4 ;dst indexed? bge.s @DoDirectNOPCheck tst.l bcolor(a6) ;bcolor a NOP? bne @CheckColorizeNOPDone move.l fcolor(a6),d1 ;fcolor a NOP? addq.l #1,d1 bne @CheckColorizeNOPDone bra.s @ClearColorizeBits ;it's a NOP, clear the colorize bits @DoDirectNOPCheck tst.l fcolor(a6) bne @CheckColorizeNOPDone ;fcolor not a NOP for direct device move.l bcolor(a6),d1 ;is fg color a NOP? lea NOPfgColorTable,a0 cmp.l (a0,d4*4),d1 bne @CheckColorizeNOPDone bra.s @ClearColorizeBits ;it's a NOP, clear the colorize bits @DeepSrc ; ; if swapfgbgBit is set, we need to swap RGB fg/bg color ; move.w d0,XLateFlag(a6) ;save translation flags btst #swapfgbgBit,XLateFlag+1(a6) ;rgb invert? beq.s @DontSwap ;don't invert PEA RGBBgColor(a6) PEA RGBFrColor(a6) ;get fg color for colorizing bra.s @SwapDone @DontSwap PEA RGBFrColor(a6) ;get fg color for colorizing PEA RGBBgColor(a6) @SwapDone _GetBackColor ;get bg color for colorizing _GetForeColor ; ; convert 16-16-16 to 8-8-8 for 32-bit src (D3=5) ; cmp.w #4,d3 ;16-bit src? beq.s @ConvertTo555 ;yes, convert to 555 move.l RGBBgColor(a6),d0 ;get RRRRGGGG lsr.l #8,d0 ;get 00RRRRGG lsl.w #8,d0 ;put green where it belongs, now 00RRGG00 move.b RGBBgColor+4(a6),d0 ;get blue: 00RRGGBB move.l d0,RGBBgColor(a6) move.l RGBFrColor(a6),d0 ;get RRRRGGGG lsr.l #8,d0 ;get 00RRRRGG lsl.w #8,d0 ;put green where it belongs, now 00RRGG00 move.b RGBFrColor+4(a6),d0 ;get blue: 00RRGGBB move.l d0,RGBFrColor(a6) move.w XLateFlag(a6),d0 ;get translation flags ; ; if RGBFrColor and RGBBgColor are white and black, colorizing is a nop so clear ; ColorizeInSrcBufBit. This is backwards from normal since it is a direct device. ; tst.l RGBFrColor(a6) ;is Fr color black, ie a NOP for colorizing? bne.s @CheckColorizeNOPDone ;no, colorizing is not a nop cmp.l #$00FFFFFF,RGBBgColor(a6) ;is bg color white ($00FFFFFF) (a NOP) bne.s @CheckColorizeNOPDone @ClearColorizeBits and.w #~(ColorizeInSrcBuf+ScaleColor),d0 ;turn off SrcBuf and scale case colorizing bra.s @CheckColorizeNOPDone ; ; convert 16-16-16 to 5-5-5 for 16-bit src (D3=4) ; @ConvertTo555 moveq #0,d0 ;clear alpha move.w RGBBgColor(a6),d0 ;get RRRR lsl.l #5,d0 ;put correct red in high word move.w RGBBgColor+2(a6),d0 ;get GGGG lsl.l #5,d0 ;put correct green in high word move.w RGBBgColor+4(a6),d0 ;get BBBB lsl.l #5,d0 ;put correct blue in high word swap d0 move.w d0,RGBBgColor(a6) move.w d0,RGBBgColor+2(a6) moveq #0,d0 ;clear alpha move.w RGBFrColor(a6),d0 ;get RRRR lsl.l #5,d0 ;put correct red in high word move.w RGBFrColor+2(a6),d0 ;get GGGG lsl.l #5,d0 ;put correct green in high word move.w RGBFrColor+4(a6),d0 ;get BBBB lsl.l #5,d0 ;put correct blue in high word swap d0 move.w d0,RGBFrColor(a6) move.w d0,RGBFrColor+2(a6) ; ; if RGBFrColor and RGBBgColor are white and black, colorizing is a nop so clear ; ColorizeInSrcBufBit. This is backwards from normal since it is a direct device. ; move.w XLateFlag(a6),d0 ;save translation flags tst.l RGBFrColor(a6) ;is Fg color black, ie a NOP for colorizing? bne.s @CheckColorizeNOPDone ;no, colorizing is not a nop cmp.l #$7FFF7FFF,RGBBgColor(a6) ;is bg color white ($00FFFFFF) (a NOP) 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 BTST #5,D2 ; the ivert flag and skip bit 2 clear BNE.S @notnot ; BCLR #2,D2 ;TEST AND CLR INVERT BIT SNE D7 ;set byte flag in d7 EXTB.L D7 ;INVERTED; D7 GETS ALL 1'S @notnot MOVE.L D7,INVERTFLAG(A6) ;SAVE INVERT FLAG ; move.w d2,locMode(a6) ;store for modecase, BitBlt, RgnBlt _PATEXPAND ;EXPAND PATTERN ;---------------------------------------------------- ; ; HIDE THE CURSOR IF TO THE SCREEN AND INTERSECTS MINRECT ; (A5 must contain global ptr) ; NOTPAT TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? BEQ.S NOTSCREEN ;=>NO PEA MINRECT(A6) ;PUSH SHIELD RECT MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL _SHIELDCURSOR ;REMOVE CURSOR IF INTERSECT NOTSCREEN ;---------------------------------------------------------------- ; ; SET UP SRC ROWBYTES, MASK ROWBYTES, AND DST ROWBYTES ; GET SRCPIX INTO A4 AND DSTPIX INTO A5 ; GET SRCRECT INTO A2 AND DSTRECT INTO A3 ; LEA SRCPIX(A6),A4 ;POINT TO SRCPIX MOVE #nuRBMask,D0 ;GET MASK FOR ROWBYTE FLAGS EXT.L D0 ;MAKE IT LONG MOVE ROWBYTES(A4),D1 ;GET SRC ROWBYTES AND.L D0,D1 ;CLEAR OUT FLAG BITS MOVE.L D1,SRCROW(A6) ;SRCROW := SRC ROWBYTES @1 LEA MASKPIX(A6),A0 ;POINT TO MASKPIX MOVE ROWBYTES(A0),D1 ;GET DST ROWBYTES AND.L D0,D1 ;CLEAR OUT FLAG BITS MOVE.L D1,MASKROW(A6) ;MASKROW := MASK ROWBYTES LEA DSTPIX(A6),A5 ;POINT TO DSTPIX MOVE ROWBYTES(A5),D1 ;GET DST ROWBYTES AND.L D0,D1 ;CLEAR OUT FLAG BITS MOVE.L D1,DSTROW(A6) ;DSTROW := DST ROWBYTES MOVE.L srcRect(a6),a2 ;get srcRect 24 bit ptr @@@@ BAL 12Jan89 MOVE.L a2,d0 ;get srcRect ptr @@@@ BAL 09Apr88 _rTranslate24To32 move.l d0,srcRect(a6) ;save 32 bit ptr @@@@ BAL 07Jul88 MOVE.L dstRect(a6),a3 ;get dstRect 24 bit ptr @@@@ BAL 12Jan89 MOVE.L a3,d0 ;get dstRect ptr @@@@ BAL 09Apr88 _rTranslate24To32 move.l d0,dstRect(a6) ;save 32 bit ptr @@@@ BAL 07Jul88 ;---------------------------------------------------------------- ; ; IF PATTERN MODE, GO DECIDE BETWEEN RGNBLT AND BITBLT ; MOVE LOCMODE(A6),D0 ;GET MODE ROR #4,D0 ;IS PATTERN BIT SET ? BCS NOTSTR ;=>YES, DON'T USE STRETCH ;---------------------------------------------------------------- ; ; CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT. ; IF NUMER = DENOM AND SRC DEPTH = DST DEPTH THEN JUST CALL RGNBLT. ; MOVE BOTTOM(A2),D1 SUB TOP(A2),D1 ;CALC SRC HEIGHT SWAP D1 ;PUT IN HI WORD MOVE RIGHT(A2),D1 SUB LEFT(A2),D1 ;CALC SRC WIDTH MOVE D1,D0 ;COPY SRC PIXCNT SUBQ #1,D0 ;MAKE IT 0 BASED MOVE D0,SRCPIXCNT(A6) ;SAVE SRC PIXEL COUNT MOVE BOTTOM(A3),D0 SUB TOP(A3),D0 ;CALC DST HEIGHT SWAP D0 ;PUT IN HI WORD MOVE RIGHT(A3),D0 SUB LEFT(A3),D0 ;CALC DST WIDTH _BlitCase ;Go determine blit style ;---------------------------------------------------------------- ; ; Determine whether to use Stretch, Scale, Rgn, or Bit Bliting ; BlitCase clr.b FastCase(a6) ;assume not a fun case 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 beq XScaleBLT ;nil table so must remap colors move.l d2,a0 ;get handle for deref MOVE.L (A0),A0 ;POINT TO IT MOVE.L CTSEED(A0),D2 ;GET SEED MOVE.L DSTPIX+PMTABLE(A6),A0 ;GET DST COLOR TABLE HANDLE MOVE.L (A0),A0 ;POINT TO IT CMP.L CTSEED(A0),D2 ;DO THE SEEDS MATCH? BNE xScaleBlt ;=>NO, use scaleBlt NOTSTR ;---------------------------------------------------------------- ; ; NOW DECIDE BETWEEN BITBLT AND RGNBLT ; ; ARE ALL THREE REGIONS RECTANGULAR ? IF SO, USE BITBLT. ; ; If the visRgn or the clipRgn is non-rectangular then call TrimRect ; to see if the intersection of the region and MinRect is rectangular, ; empty, or regional. 08Nov87 BAL ; MOVEQ #10,D0 ;GET SIZE OF RECT RGN MOVE.L RGNC(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT CMP RGNSIZE(A0),D0 ;IS RGNC RECTANGULAR ? BNE XRGNBLT ;=>NO, USE RGNBLT @chkVis MOVE.L RGNB(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT CMP RGNSIZE(A0),D0 ;IS visRgn RECTANGULAR ? BEQ.S @chkClip ;=>yes, go check clipRgn MOVE.L RGNB(A6),-(SP) ;PUSH visRgn HANDLE PEA MINRECT(A6) ;PUSH ADDR OF MINRECT MOVE.W #-1,-(SP) ;pass Trim = True _TRIMRECT ;CALL TRIMRECT BLT DONE ;=>INTERSECTION EMPTY, QUIT & SHOW CURSOR BGT XRGNBLT ;=>USE RGNBLT ; In case we fall into RgnBlt, replace visRgn with WideOpen ; so that TrimRect doesn't get called again by seekMask. MOVE.L SAVEA5(A6),A1 ;Get global ptr MOVE.L GRAFGLOBALS(A1),A1 ;point to QD globals MOVE.L WIDEOPEN(A1),RGNB(A6) ;replace visRgn with wideOpen @chkClip ; ;<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 PEA MINRECT(A6) ;PUSH ADDR OF MINRECT MOVE.W #-1,-(SP) ;pass Trim = True _TRIMRECT ;CALL TRIMRECT BLT DONE ;=>INTERSECTION EMPTY, QUIT & SHOW CURSOR BEQ XBITBLT ;=>USE BITBLT ; Since we will fall into RgnBlt, swap the clipRgn and the userRgn ; so that TrimRect doesn't get called again by seekMask. MOVE.L RGNA(A6),A1 ;copy clipRgn MOVE.L RGNC(A6),RGNA(A6) ;replace clipRgn with userRgn MOVE.L A1,RGNC(A6) ;replace userRgn with clipRgn BRA XRGNBLT ;=>USE RGNBLT XScaleBLT ;-------------------------------------------------------------- ; ; Must do depth scaling but no spatial resizing and no bit mask. ; Only supports copy and dither modes. No fg/bk colorizing. ; No search procs supported for direct sources. ; ; REGISTER USE: ; ; A2: SRCRECT (24 bit addr) ; A3: DSTRECT (24 bit addr) ; A4: SRCPIX ; A5: DSTPIX ; ; D3: SRCSHIFT ; D4: DSTSHIFT ; D7: INVERT FLAG tst locMode(a6) ;copy mode? bne Stretch ;if not copy mode then use stretch ; ; Use Stretch if an alpha mode is set by looking at the streamMode <23JUN92 SAH> ; ; Rather than looking at the stream mode directly here, we should add a call to the alpha ; routines that returns the alpha mode so that we can localize the code! Do this before it ; goes into ROM! ; move.l savea5(a6),a0 ;get the real a5 move.l GrafGlobals(a0),a0 ;get the qd globals move.l thePort(a0),a0 ;get the port TST portBits+rowBytes(A0) ;is it an old port? BPL @noalpha ;yes, alpha mode is illegal MOVE.W dstPix+pixelSize(A6),D2 ;get depth of destination CMP.W #16,D2 ;direct device? BLT.S @noalpha ;no, skip this stuff MOVE.L grafVars(A0),D2 ;get grafvars handle BEQ @noalpha ;no grafvars, no alpha MOVE.L D2,A0 ;copy handle MOVE.L (A0),A0 ;dereference handle BTST #PmNewGVBit-8,pmFlags(A0) ;make sure grafvars have been expanded BEQ.S @noalpha ;if not, bail TST.B streamMode(A0) ;is there an alpha mode bne Stretch ;yes, so go slow ; ; now look at the actual alpha channel byte/bit to see if it contains zero. If not, we ; must go slow. This is because a streamMode of zero means that we write to both graphics ; and alpha. As an optimization, we might be able to just do this check alone for any ; streamMode so that we can go fast when writing an alpha of zero. ; ; For the purposes of Cube-E, this code is remaining as it is below, but it would be wise ; to make the tests just test memory directly to save code space! ; MOVE.W dstPix+pixelSize(A6),D2 ;get depth of destination cmp.w #16,d2 ;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? beq.s @fast ;no, go fast @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 _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) ; MOVE.L SRCPIX+PMTABLE(A6),d0 ;GET SRC COLOR TABLE HANDLE <2Sep90 KON> beq.s @BAL ;table not nil so continue <2Sep90 KON> MOVE.L d0,a0 MOVE.L (A0),d0 ;POINT TO IT <2Sep90 KON> _rTranslate24To32 ;clean master pointer <20AUG90 KON and BAL> move.l d0,SrcPixPmTable(a6) ; <20AUG90 KON and BAL> @BAL ;---------------------------------------------------------------- ; ; DETERMINE AMOUNT OF STACK SPACE WE CAN USE ; Raised amount left for interupts from 1024 to 1600 bytes ; _StackAvail ;GET STACK AVAIL IN D0.L LSR.L #2,D0 ;CONVERT BYTES TO LONGS SUB.L #qdStackXtra/4,D0 ;SUBTRACT SLOP FACTOR <1.5> BAL MOVE.L D0,STACKFREE(A6) ;AND SAVE FREE LONGS ON STACK bpl.s @stkOK _stNoStack ;=>NOT ENOUGH STACK, QUIT @stkOK ;---------------------------------------------------------------- ; ; Check to see if we are shrinking 16 or 32 bit source data OR if we are ; shrinking a deep mask. If we are, allocate a buffer for the larger of the ; two. *** Currently assuming source and mask are the same size *** ; clr.b useAverage(a6) ;assume not averaging move.w numer+v(A6),D0 ; get destination height move.w denom+v(A6),D1 ; get source height cmp.w d1,d0 ;is source larger than dest? bge.s @noAvrg ;NO=> don't average ;yes, so average if 32 bit/pixel or deep mask cmp.w #4,d3 ;is src indexed? blt.s @noAvrg ;yes, skip averaging @shrink sge useAverage(a6) ;always average if 16 or 32bit src moveq #0,d1 move.w denom+h(a6),d1 ;src width move.l d1,d2 ;make a copy src width <16Feb90 KON and BAL> add.l d2,d2 ;6 bytes (R.w,G.w,B.w) per pixel add.l d1,d2 ;d2 is byte cnt/2 of AvrgBuf ; ; allocate the larger of source buffer or mask buffer ; cmp.w #4,maskshift(a6) ;mask 16-bit data? beq.s @DoWords ;yes, allocate twice the error buffer ; cmp.w #4,d3 ;source 16-bit data? cmp.w #4,realSrcShift(a6) ;source 16-bit data (check real source)? beq.s @DoWords ;Twice as many pixels, allocate twice the error buffer lsr.l #1,d2 ;both 32-bit, 1/2 as many pixels @DoWords move.w d2,ABufSize(a6) ;save long cnt for later SUB.L D2,STACKFREE(A6) ;IS THERE ENOUGH STACK? bpl.s @stkOK2 _stNoStack ;=>NOT ENOUGH STACK, QUIT @stkOK2 CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP @ClrBuf CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG DBRA D2,@ClrBuf ;LOOP ENTIRE BUFFER MOVE.L SP,AvrgBuf(A6) ;REMEMBER WHERE AvrgBuf IS @noAvrg ;---------------------------------------------------------------- ; ; if dstPix is direct and we aren't averaging then no ; reason to promote source to RGB, unless using deep mask. ; tst.b realDepth(a6) ;promoting src to RGB? bmi.s @LeaveItAlone ;no, all ok cmp.w #16,dstPix+pixelType(a6) ;is dst direct data? bne.s @LeaveItAlone ;no, we will be dithering tst.b useAverage(a6) ;are we averaging bne.s @LeaveItAlone ;yes, promote source tst.w maskshift(a6) ;deep mask? bne.s @LeaveItAlone ;yes: promote ; ;no, don't promote source ; move.w realDepth(a6),srcPix+pixelSize(a6) move.w realSrcShift(a6),d3 ;don't fake 32-bit source move.w d3,srcShift(a6) ;remember it for later st realDepth(a6) ;don't expand source to 32-bit clr.w SRCPIX+pixelType(A6) ;don't fake ; ; Change colorizing back to Scalecase colorizing since the scale table ; is used for indexed sources. <12NOV90 KON> ; bclr #ColorizeInSrcBufBit,XLateFlag(a6) ;colorize at srcbuf time? beq.s @NoColorizing ;no, we're cool ; ; colorizing -> change back to scalecase colorizing ; bset #ScaleColorBit,XLateFlag+1(a6) ;Colorize in scale table @NoColorizing @LeaveItAlone ;---------------------------------------------------------------- ; ; IF THE SRC AND DST ARE DIFFERENT DEPTHS, THEN MUST DO PIXEL SCALING ; IF THEY ARE THE SAME DEPTH, BUT DIFFERENT COLOR TABLES, DO PIXEL SCALING ; CLR.L SCALECASE(A6) ;ASSUME NO PIXEL DEPTH SCALING MOVE.W SRCPIX+pixelType(A6),D0 ;IS PIXELTYPE DIRECT? %%% BEQ HasClut ;NO, IT HAS A CLUT %%% cmp #16,d0 ;is it RGBDirect? bne done ;unknown pixeltype -> go home ;@@@@ should also check cmpCount, cmpSize MOVE.L ([theGDevice]),A2 ; get the current device (trash A2) tst.l gdSearchProc(A2) ; get the search proc head bne.s @Slow cmp d3,d4 ;are the depths the same beq PIXELOK ;yes, don't depth scale ;---------------------------------------------------------------- ; ; The src is direct data (16 or 32 bits/pixel). ; Compute D5 as index into direct mode table based on ; ; src16 -> add 4 ; dstIndexed -> add 1 ; searchProc -> add 16 ; dithering -> add 2 ; dst16 -> add 2 ; dstAllGray -> add 8 ; ; D3=srcShift D4=dstShift ; @Slow moveq #4,d0 ; init direct scaleRtn with src=16 move.l d0,d5 cmp.w d3,d5 ; is src 16 bits/pixel? beq.s @src16 moveq #0,d5 ; init src to 32 bits/pixel @src16 cmp.w d4,d0 ; is dst 16 bits/pixel? bne.s @dst32 addq #2,d5 ; remember dst is 16 bits/pixel @dst32 cmp #16,DSTPIX+pixelType(A6) ;IS PIXELTYPE DIRECT? %%% beq @noCLUT ;don't makeItable on direct device ; IF THE DST IS AN OLD GRAFPORT AND ONE BIT PER PIXEL, THEN OVERRIDE THE ; scaleCase FOR PROPER MAPPING TST d4 ;ONE BIT PER PIXEL? BNE.S @notBitmap ;=>NO, PROC IS OK MOVE.L DSTBITS(A6),A1 ;GET DST BITMAP TST ROWBYTES(A1) ;IS IT OLD? BMI.S @notBitmap ;=>NO, PROC IS OK addq #8,d5 ;force bitmap procs bra @chkDither ;go check dither @notBitmap addq #1,d5 ; remember dst is indexed MOVE.L ([GDPMap,A2]),A1 ; get pixMap's handle MOVE.L PMTable(A1),A0 ; get the device colorTable's handle MOVE.L ([A0],CTSeed),D1 ; get the device colorTable's ctSeed MOVE.L ([GDITable,A2]),A0 ; get the Itable's master pointer CMP.L ITabSeed(A0),D1 ; has the colortable changed? BEQ.S @1 ; if equal, then the iTable is OK ; if table is not up to date, build a new one MOVE.L PMTable(A1),-(SP) ; push theGDevice's color table handle MOVE.L GDITable(A2),-(SP) ; push theGDevice's current iTabHandle MOVE.W GDResPref(A2),-(SP) ; push the preferred iTableResolution _MakeITable ; make a new table TST.W QDErr ; was this sucessful? BEQ.S @noErr ; nope, so quit ADDQ #4,SP ; flush saved register BRA doneErr ; @noErr MOVE.L ([theGDevice]),A2 ; redereference in case it moved MOVE.L ([GDITable,A2]),A0 ; get the iTable's master pointer @1 ADD.w #ITTable,A0 ; point directly at data MOVE.L A0,stITabPtr(A6) ; save in stack frame SUB.w #ITTable,A0 ; get the iTable's master pointer MOVE.W ITabRes(A0),stITabRes(A6) ; get the iTable resolution MOVE.L ([GDPMap,A2]),A1 ; get pixMap's handle MOVE.L ([PMTable,A1]),stCLUTPtr(A6) ; get the device colorTable's ptr MOVE.L gdSearchProc(A2),D0 ; get the search proc head bne.s @search ; go use search routines ; Here we know that the dst is indexed and no search proc is present, ; so determine if the dst clut is all grays and/or we are dithering. ; the iTable's master pointer is in A0 MOVEQ #1,D0 ; prime the register again MOVE ITabRes(A0),D2 ; get the inverse table resolution (and Bit-field width) LSL.L D2,D0 ; calculate 2^^res LSL.L D2,D0 ; square it LSL.L D2,D0 ; cube it LEA ITTable(A0,D0.L),A1 ; point us at the ITabInfo tst.w iTabFlags(a1) ; is this a grayITab? bpl.s @chkDither ; no, go see if dithering add.w #ITabInfo,a1 ; point past header move.l a1,stITabInfo(a6) ; save for later addq #8,d5 ; remember to use gray routines moveq #40,d0 cmp.l ITabSeed(a0),d0 ; is dst the standard 8-bit gray clut? beq.s @readyProc ; yes, ignore dithering for speeed! @chkDither tst.b useDither(a6) ; should we dither? beq.s @readyProc ; no, we're set addq #2,d5 ; remember to use dither routines ; ; Compute and allocate scanline buffer for dither error from previous scan ; MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0 MOVE NUMER+H(A6),D0 ;GET WIDTH OF DST lsl.l d4,d0 ;get bit width add.l #31,d0 ;round to long boundary lsr.l d4,d0 ;get adjusted pixel width btst #3,d5 ;is dst a grayscale clut? bne.s @gray ;only need 2 bytes per pixel for gray error move.l d0,d1 ;make a copy ADD.l D0,D0 ;6 bytes (R.w,G.w,B.w) per pixel add.l d1,d0 ;d0 is byte cnt/2 of ErrBuf @gray LSR.l #1,D0 ;AND DIV BY 2 FOR LONGS SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK? bpl.s @stkOK3 _stNoStack ;=>NOT ENOUGH STACK, QUIT @stkOK3 CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP @ClearB CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG DBRA D0,@ClearB ;LOOP ENTIRE BUFFER MOVE.L SP,ErrBUF(A6) ;REMEMBER WHERE ErrBuf IS clr.b ErrDir(a6) ;init to carry error to right BRA.S @readyProc ; and continue ; Here we know that the dst is direct so check if search proc is present. @noCLUT MOVE.L gdSearchProc(A2),D0 ; get the search proc head beq.s @readyProc @search MOVE.L D0,stSProc(A6) ; put search procs list head in stack frame bset #4,d5 ; use search routines ; We have the scaleCase routine selector in D5 so compute address ; of routine and stuff it in scaleCase for later @readyProc move.w d5,d0 ;copy selector lsr.w #3,d0 ;determine table to use lea (stColorTabPtr,ZA0,d0*4),A0 ;POINT TO MODE TABLE move.l (a0),a0 ;get table and.w #7,d5 ;get position in this table add.l 0(A0,D5*4),A0 ;GET CASE JUMP ADDRESS MOVE.L A0,scaleCase(A6) ; put depth scaling routine in stack frame BRA PIXELOK ;=>ALREADY GOT ROUTINE ;---------------------------------------------------------------- ; ; The src is indexed data (1,2,4,8 bits/pixel). ; If seeds don't match or depths are different then make a scale table. ; Special case 1-bit source. ; HasClut MOVE.L SRCPIX+PMTABLE(A6),d0 ;GET SRC COLOR TABLE HANDLE beq.s DOXLATE ;table not nil so continue move.l d0,a0 ;get handle for deref MOVE.L (A0),a0 ;POINT TO IT MOVE.L CTSEED(A0),D0 ;GET SEED MOVE.L DSTPIX+PMTABLE(A6),A0 ;GET DST COLOR TABLE HANDLE cmp #16,DstPix+pixelType(a6) ;is it a direct device? beq.s @chk1 ;yes, don't check seeds MOVE.L (A0),A0 ;POINT TO IT CMP.L CTSEED(A0),D0 ;DO THE SEEDS MATCH? BNE.S @chk1 ;=>NO, MUST TRANSLATE CMP D3,D4 ;DOES SRC DEPTH = DST DEPTH? bne.s @chk1 ;no, then scale pixels ; ; check fg and bk color and if they aren't black and white ; then take chk1 case, otherwise, take pixelok case. ; ; begins here... This fixes a problem with drawing to bitmaps. The problem ; is when the main device is direct and the app sets the fg color to black and the ; bg color to white, we think we are colorizing since the sense of what is black and ; what is white is reversed. This can only happen when the destination pixmap is ; 1-bit and the destination GDevice is a direct device. Thus, I special case this ; situation and check the fg and bg colors for black and white correctly. There is ; probably a more elegant fix for this, but with 7.0 ready to ship this implementation ; causes the least risk since it should effect only the case we are interested in. If ; it's not this particular case, we branch to @OldWay and processing continues as before. ; YUK! ; ; 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 ; 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 ; beq PIXELOK ;bk white, fg black, go fast @chk1 TST D3 ;IS SRC ONE BIT PER PIXEL? BNE.S DOXLATE ;=>NO, Build mapping table MOVEQ #1,D1 ;GET CTSEED FOR DEFAULT ONE BIT TABLE CMP.L D0,D1 ;IS IT THE DEFAULT? BEQ SRCONE ;=>YES, USE EXPAND TABLES FOR SPEED DOXLATE MOVE SRCPIX+PIXELSIZE(A6),D1 ;GET SRC BITS PER PIXEL MOVEQ #1,D0 ;# ENTRIES = 2^ PIXELSIZE LSL D1,D0 ;CALC # ENTRIES SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK? bpl.s @stkOK _stNoStack ;=>NOT ENOUGH STACK, QUIT @stkOK ; IF THE DST IS AN OLD GRAFPORT AND IS ONE BIT PER PIXEL, THEN OVERRIDE THE ; SEARCH PROC FOR PROPER MAPPING MOVEQ #0,D7 ;ASSUME NO PROC INSTALLED CMP #1,DSTPIX+PIXELSIZE(A6) ;ONE BIT PER PIXEL? BNE.S @PROCOK ;=>NO, PROC IS OK MOVE.L DSTBITS(A6),A1 ;GET DST BITMAP TST ROWBYTES(A1) ;IS IT OLD? BMI.S @PROCOK ;=>NO, PROC IS OK MOVEQ #1,D7 ;FLAG PROC INSTALLED PEA ONEBITPROC ;POINT TO OUR PROC _ADDSEARCH ;AND INSTALL IT @PROCOK MOVE.L SAVEA5(A6),A5 ;GET A5 FOR MAKESCALETBL MOVE.L A4,-(SP) ;PUSH SRCPIX POINTER ; ; If bit 0 = 1, then MakeScaleTbl colorizes, otherwise it don't. ; if mode is BIC or OR, then don't colorize in MakeScaleTbl ; MOVE.w XLateFlag(a6),-(SP) ;pass arithmetic mode to get fg/bg relative colors _MakeScaleTbl ;AND MAKE PIXEL TRANSLATION TABLE ;------------------------------------------------------------------------------------------ ; ; 08Nov87 BAL begins here: ; ;------------------------------------------------------------------------------------------ ; ; MakeScaleTbl is called whenever the src and dst pixmaps have different ; pixel depths or different color table seeds. MakeScaleTbl returns a ; pixel translation table used to map each src pixel to a dst pixel. ; ; Here I check to see if the translation table returned by MakeScaleTbl is in ; actuality an identity mapping--in which case no mapping at all is required! ; In order for an identity mapping to result the src and dst pixMaps must be of the same ; depth. ; ; If an identity mapping is detected, I must decide whether a stretch blit loop is ; really required (ie src rect ­ dst rect or maskBits ­ nil) or whether a much faster ; region blit or bit blit loop would suffice. ; ;------------------------------------------------------------------------------------------ move SRCPIX+PIXELSIZE(A6),d1 ;get src bits/pixel cmp DSTPIX+PIXELSIZE(A6),d1 ;is it the same as dst bits/pixel? bne.s @ScaleOK ;no, have to do pixel scaling ;inspect scale table for equality @chkTbl MOVEQ #1,D0 ;# ENTRIES = 2^ PIXELSIZE LSL D1,D0 ;CALC # ENTRIES in d0 move d0,d1 ;make a copy of long count lsl #2,d1 ;get size of table subq #1,d0 ;make counter zero based for dbra move.l sp,a0 ;point to scale tbl add d1,a0 ;point past end of table @1 cmp.l -(a0),d0 ;compare with dst pixel value dbne d0,@1 bne.s @ScaleOK ;tables are not equal so perform pixel scaling CLR.L ScaleCase(a6) ;remember no pixel xlation needed MOVE.L SP,ScaleTbl(A6) ;SAVE TRANSLATION TABLE just in case ;if we installed a proc get rid of it before short circuiting stretch TST D7 ;DID WE INSTALL A PROC BEQ.S @NOPRC ;=>NO, DON'T NEED TO REMOVE PEA ONEBITPROC ;ELSE PUSH OUR PROC _DELSEARCH ;AND DELETE IT @NOPRC LEA DSTPIX(A6),A5 ;RESTORE DSTPIX POINTER TST.L MASKBITS(A6) ;*** IS THERE A MASK? BNE PIXELOK ;=>YES, USE STRETCH BUT DON'T PIXEL TRANSLATE ;---------------------------------------------------------------- ; ; CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT. ; IF NUMER = DENOM AND SRC DEPTH = DST DEPTH THEN JUST CALL RGNBLT. ; MOVE.L NUMER(A6),D0 ;GET WIDTH,HEIGHT OF DST CMP.L DENOM(A6),D0 ;SAME AS WIDTH,HEIGHT OF SRC? BNE PIXELOK ;no, must call stretch MOVE.L INVERTFLAG(A6),D7 ;restore invert flag <> BRA NOTSTR ;jump back and decide between bitblt and rgnblt ;don't really have to use stretch at all! ;------------------------------------------------------------------------------------------ ; ; 08Nov87 BAL ends here. ; ;------------------------------------------------------------------------------------------ @ScaleOK MOVE.L SP,ScaleTbl(A6) ;SAVE POINTER TO TRANSLATION TABLE LEA DSTPIX(A6),A5 ;RESTORE DSTPIX POINTER TST D7 ;DID WE INSTALL A PROC BEQ.S @NOPROC ;=>NO, DON'T NEED TO REMOVE PEA ONEBITPROC ;ELSE PUSH OUR PROC _DELSEARCH ;AND DELETE IT @NOPROC move.l stIndexedSrc,A0 ;POINT TO THE SCALING ROUTINE MOVE.L A0,SCALECASE(A6) ;AND SAVE CASE JUMP FOR LATER BRA PIXELOK ;=>ALREADY GOT ROUTINE ALIGN Alignment ONEBITPROC ;---------------------------------------------------------------- ; FUNCTION ONEBITPROC(MYCOLOR:RGBCOLOR; VAR INDEX: LONG): BOOLEAN; ; ; THIS IS A COLOR MANAGER CUSTOM SEARCH PROC THAT MAPS RGB TO ; BLACK AND WHITE FOR MAPPING TO OLD GRAFPORTS. ; Algorithm modified to use [5 9 2] luminance mapping. ; MYINDEX EQU 4 MYRGB EQU 8 RESULT EQU 12 ST.B RESULT(SP) ;ALWAYS RETURN TRUE MOVE.L MYRGB(SP),A0 ;POINT TO RGB moveq #0,d0 ;clear out high end moveq #0,d1 ;clear out high end move.w red(a0),d0 ;get red move.l d0,a1 ;keep red in a1 move.w green(a0),d1 ;get green add.l d0,d1 ;accumulate luminance in d1 move blue(a0),d0 add.l d0,d1 ;accumulate luminance in d1 add.l d0,d1 ;accumulate luminance in d1 lsr.l #2,d1 add.l a1,d1 ;accumulate luminance in d1 move green(a0),d0 add.l d0,d1 ;accumulate luminance in d1 add.l d0,d1 ;accumulate luminance in d1 lsr.l #2,d1 MOVE.L MYINDEX(SP),A1 ;POINT TO INDEX CLR.L (A1) ;ASSUME INDEX = WHITE tst d1 ;check luminance BMI.S @RESOK ;=>IF >= $8000 THEN WHITE ADDQ.L #1,(A1) ;ELSE RETURN BLACK @RESOK RTD #8 ;STRIP PARAMS AND RETURN 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 08Nov87 BAL ; NOSCALE MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT MOVE LEFT(A0),D1 ;GET DSTRECT LEFT SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL COORDS LSL.L D4,D1 ;CONVERT DST PIXELS TO BITS AND #$FFE0,D1 ;TRUNC TO MULT OF 32 ASR.L D4,D1 ;CONVERT DST BITS TO PIXELS ADD BOUNDS+LEFT(A5),D1 ;CONVERT BACK TO LOCAL MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT MOVEQ #0,D0 ;CLEAR HIGH WORD OF D0 MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT SUB D1,D0 ;CALC WIDTH IN DOTS MOVE D0,bufSize(A6) ;for arithmetic modes, prime bufSize with dot size move d0,d1 ;save for expansion scanline buffer ext.l d1 ;clear out high word lsl.l d4,d1 ;convert to bits subq.l #1,d1 ;force downward round LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 addq.l #1,d1 ;***make it one based for stretch!! BTST #5,locMode+1(A6) ;arithmetic? BNE.S @skipDotToLong ;if so, donÕt update bufSize MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 @skipDotToLong LSR #5,D0 ;GET NUMBER OF LONGS IN SCANBUF ADDQ #1,D0 ;MAKE IT ONE BASED LSL D4,D0 ;MULTIPLY BY DST PIXEL DEPTH ;*** Leave it one based !!!? SUB.L D0,STACKFREE(A6) ;IS THERE ENOUGH STACK? bpl.s @stkOK _stNoStack ;=>NOT ENOUGH STACK, QUIT @stkOK ;----------------------------------------------------------------------- ; ; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK. ; CLR.L -(SP) ;TWO FOR SLOP CLR.L -(SP) ;ONE FOR SLOP CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR DBRA D0,CLRMASK ;LOOP TILL DONE MOVE.L SP,RGNBUFFER(A6) ;REMEMBER WHERE RGNBUFFER IS ;-------------------------------------------------------------------- ; ; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION ; GET SEEK ROUTINE INTO SEEKMASK(A6) ; GET EXPAND ROUTINE INTO EXRTN(A6) FOR SEEK ROUTINE ; Clobbers: A0-A3, D0-D6 ; move.l stNoStackPtr,goShow(a6) ;pass go home routine to getSeek clr.l runBuf(a6) ;don't use run clipping <1.5> BAL move.l dstmaskbuf(a6),d7 ;save dstmaskbuf tst.w maskshift(a6) ;deep mask? beq.s @dontTrickGetSeek ;branch if no clr.l dstmaskbuf(a6) ;make seek think there is no mask @dontTrickGetSeek MOVE.L RGNC(A6),-(SP) ;PUSH USER RGNHANDLE (never TrimRect'ed) MOVE.L RGNB(A6),-(SP) ;PUSH VIS RGNHANDLE MOVE.L RGNA(A6),-(SP) ;PUSH CLIP RGNHANDLE MOVE.L #2,-(SP) ;PUSH HANDLE COUNT - 1 _GETSEEK ;GET EXPAND ROUTINE INTO EXRTN(A6) ;AND SEEK ROUTINE INTO SEEKMASK(A6) move.l d7,dstmaskbuf(a6) ;restore ;-------------------------------------------------- ; ; CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES ; GET INVERTFLAG INTO D7 ; SETMODE MOVE LOCMODE(A6),D0 ;GET THE MODE BTST #5,D0 ;arithmetic mode? BEQ.S @notArithMode CMP #$40,D0 ;source modes are $20 É $27, $32 BGT DONE ;if bigger, undefined BTST #3,D0 ;pattern? BNE DONE AND #$17,D0 ;consider only 8 mode variants BCLR #4,D0 ;clear hilite bit BEQ.S @notHilite SUBQ #2,D0 ;hilite? BNE DONE ADDQ #8,D0 ;advance to hilite ($0C - 4) @notHilite cmp #16,dstPix+pixelSize(A6) ;dst 32 bits/pixel? bge.s @useLoops16 ;yes, use alternate table ADDQ #4,D0 ;advance past normal src modes BRA.S @setupJump @useLoops16 bne.s @useLoops32 ;yes, use alternate table move.l stArith16TabPtr,A0 ;POINT TO 16 bit MODE TABLE @getMode BCLR #4,D0 ;clear hilite bit add.l 0(A0,D0*4),A0 ;GET CASE JUMP ADDRESS move.l a0,modeCase(a6) ;save for later bra.s @gotMode @useLoops32 move.l stArith32TabPtr,A0 ;POINT TO 32 bit MODE TABLE bra.s @getMode @notArithMode MOVE.L INVERTFLAG(A6),D7 ;GET THE INVERT FLAG BCLR #2,D0 ;CLEAR INVERT BIT CMP #7,D0 ;IS MODE > 7 ? BGT DONE ;YES, QUIT @setupJump LEA StretchModeTab,A0 ;POINT TO MODE TABLE (in trap table) MOVE.L 0(A0,D0*4),MODECASE(A6) ;SAVE FOR LATER @gotMode ;------------------------------------------------ ; ; SET UP srcMergeCase ; @noPromote move.w srcshift(a6),d3 ;src depth lea VMergeTable,a0 ;get base add.l (a0,d3.w*4),a0 ;get routine offset from base move.l a0,srcMergeCase(a6) SourceMergeSetupDone ;------------------------------------------------ ; ; SET UP maskMergeCase ; clr.l CombineMaskCase(a6) ;assume no mask clr.l maskMergeCase(a6) ;assume no mask tst.l maskbits(a6) ;is there a mask? beq nomask1 ;=>NO move.w maskshift(a6),d0 ;mask depth, currently 0, 4, or 5 lea VMergeTable,a0 ;get base add.l (a0,d0.w*4),a0 ;get displacement to routine move.l a0,maskMergeCase(a6) MergeSetupDone ;------------------------------------------------ ; ; set up CombineMaskCase ; tst maskshift(a6) beq.s CombineMaskSetupDone ;one bpp mask ; ; Table is disorganized as follows: ; ; SRC DST MASK ENTRY ; 32 ind 32 0 ; 32 16 32 1 ; 32 32 32 2 ; ; calc routine based on dst ; ; ; want indexed values to goto 0, 16 bit to 1, 32 bit to 2 ; move dstshift(a6),d0 subq #3,d0 spl d1 and d1,d0 lea CombineTable,a0 ;get base add.l (a0,d0.w*4),a0 ;get displacement to routine move.l a0,CombineMaskCase(a6) CombineMaskSetupDone ;------------------------------------------------ ; ; SET UP MASKALIGN AND MASKADDR IF THERE IS A MASK ; MOVE MASKSHIFT(A6),D3 ;GET MASKSHIFT LEA MASKPIX(A6),A2 ;POINT TO MASKPIX MOVE.L MASKROW(A6),D2 ;GET MASK ROWBYTES MOVE.L MASKRECT(A6),A0 ;POINT TO MASKRECT MOVE LEFT(A0),D1 ;GET MASKRECT LEFT SUB BOUNDS+LEFT(A2),D1 ;CONVERT TO MASK GLOBAL EXT.L D1 ;MAKE LONG FOR BIG PIXELS lsl.l d3,d1 ;convert pixels to bits MOVEQ #$1F,D5 ;TREAT MOD 32 FOR MASKALIGN AND.L D1,D5 ;MAKE A COPY MOVE.L D5,MASKALIGN(A6) ;SAVE ALIGNMENT OF MASK MOVE TOP(A0),D0 ;GET MASKRECT TOP SUB BOUNDS+TOP(A2),D0 ;CONVERT TO MASK GLOBAL MULS D2,D0 ;MULT BY MASK ROWBYTES BAL 02Dec88 ADD.L BASEADDR(A2),D0 ;GET START OF MASK BITMAP SUB.L D5,D1 ;ADJUST MASKLEFT FOR MASKALIGN ASR.L #3,D1 ;CONVERT BITS TO BYTES ADD.L D1,D0 ;ADD BYTES TO MASKADDR MOVE.L D0,MASKADDR(A6) ;SAVE AS MASKADDR NOMASK1 ;---------------------------------------------------------- ; ; Jump into 32 bit addressing mode for blitting. @@@@ BAL 09Apr88 ; moveq #true32b,d0 ;switch to 32 bit addressing @@@@ BAL 09Apr88 _rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2) move.b d0,MMUsave(a6) ;save previous state for later @@@@ BAL 09Apr88 ;------------------------------------------------ ; ; SET UP SRCROW, SRCSCANS, SRCSHIFT, AND SRCADDR ; MOVE realSRCSHIFT(A6),D3 ;GET SRCSHIFT LEA SRCPIX(A6),A2 ;POINT TO SRCPIX MOVE.L SRCROW(A6),D2 ;GET SRC ROWBYTES MOVE BOUNDS+BOTTOM(A2),D1 ;GET SRCBITS.BOUNDS.BOTTOM SUB BOUNDS+TOP(A2),D1 ;MAKE IT GLOBAL MOVE D1,SRCSCANS(A6) ;SAVE NUMBER OF SCANS TO DO MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT MOVE LEFT(A0),D1 ;GET SRCRECT LEFT SUB BOUNDS+LEFT(A2),D1 ;CONVERT TO SRC GLOBAL EXT.L D1 ;MAKE LONG FOR BIG PIXELS LSL.L D3,D1 ;CONVERT SRC PIXELS TO BITS MOVEQ #$1F,D5 ;TREAT MOD 32 FOR SRCSHIFT AND.L D1,D5 ;MAKE A COPY MOVE.L D5,SRCALIGN(A6) ;SAVE ALIGNMENT OF SOURCE MOVE TOP(A0),D0 ;GET SRCRECT TOP SUB BOUNDS+TOP(A2),D0 ;CONVERT TO SRC GLOBAL MULS D2,D0 ;MULT BY SRC ROWBYTES BAL 02Dec88 ADD.L BASEADDR(A2),D0 ;GET START OF SRC BITMAP SUB.L D5,D1 ;ADJUST SRCLEFT FOR SRCSHIFT ASR.L #3,D1 ;CONVERT BITS TO BYTES ADD.L D1,D0 ;ADD BYTES TO SRCADDR MOVE.L D0,SRCADDR(A6) ;SAVE AS SRCADDR @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 tst maskshift(a6) beq.s @NoTrickorTreat clr.l dstmaskbuf(a6) ;make seek think there is no mask @NoTrickorTreat JSR ([SEEKMASK,A6]) ;MAKE MASK BUFFER CURRENT move.l a4,dstmaskbuf(a6) ; MOVE.L SCALEBUF(A6),A3 ;INIT SRCPTR MOVE.L DSTADDR(A6),A4 ;INIT DSTPTR FOR ROW MOVE.L RGNBUFFER(A6),A2 ;INIT MASKPTR FOR ROW MOVE BUFSIZE(A6),D2 ;INIT COUNT OF LONGS MOVE.L MODECASE(A6),A0 ;GET MODE CASE JUMP BTST #5,locMode+1(A6) ;an arithmetic mode? BEQ.S @skipArith MOVE.L transColor(A6),D4 ;set up transparent color in case different from bg CMP #$24,locMode(A6) ;transparent? BEQ.S @skipInvTbl ;if so, D5 contains the pixels per long value MOVE invSize(A6),D5 ;set up resolution of inverse table for arith. modes @skipInvTbl MOVEQ #0,D3 ;initialize destination pixel offset MOVE.L dstAlign(A6),D6 ;reset alignment since it is bumped by arith. modes SUB.L D7,D6 ;bump source pixel offset back by 1 @skipArith CMP.L DSTPIX+BASEADDR(A6),A4 ;IS IT BEFORE THE PIXMAP? BLO.S DSTNEG ;=>YES, DON'T PUT TO DST DOBLT 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 tst.b useDither(a6) ; are we dithering? bne.s dstOK ; yes dither this scan again with current error BRA NXTMSK1 ;ELSE continue to draw from this src ;----------------------------------------------------------------- ; ; HANDLE CASE WHERE DST IS NEGATIVE ; DSTNEG MOVE.L DSTPIX+BASEADDR(A6),D1 ;GET ELUSIVE BASE ADDRESS BTST #5,locMode+1(A6) ;AN ARITHMETIC MODE? BEQ.S @NoRith ;=>NOPE, DO NORMAL ; IF ARITHMETIC MODE, BUMP ONE PIXEL AT A TIME UNTIL DST ISN'T NEGATIVE @LOOP LEA 0(A4,D3),A1 ;GET CURRENT ADDRESS CMP.L A1,D1 ;ARE WE STILL NEGATIVE? BLS.S DOBLT ;=>NO, BLIT REST OF SCANLINE SUBQ #1,D2 ;SKIP A DOT BMI.S NEXTDST ;=>DONE WITH SCANLINE ADD.L D7,D6 ;BUMP SRC POINTER ONE DOT ADD.L D7,D3 ;BUMP DST POINTER ONE DOT BRA.S @LOOP ;=>YES, KEEP SKIPPING ; IF NORMAL MODE, BUMP ONE LONG AT A TIME UNTIL DST ISN'T NEGATIVE @NoRith LEA 4(A4),A1 ;GET NEXT LONG OF DST CMP.L A1,D1 ;ARE WE STILL NEGATIVE BLS.S DOBLT ;=>NO, BLIT REST OF SCANLINE SUBQ #1,D2 ;SKIP NEXT LONG BMI.S NEXTDST ;=>DONE WITH SCANLINE ADDQ.L #4,A2 ;BUMP MASKPTR ADDQ.L #4,A3 ;BUMP SRCPTR ADDQ.L #4,A4 ;BUMP DSTPTR BRA.S @NoRith ;=>TRY, TRY AGAIN ;----------------------------------------------------------------- ; ; ENTIRE STRETCHBITS COMPLETE. RESTORE REGS AND STACK AND GO HOME. ; DoneStretch DONE clr.w QDErr ;signal no error doneErr move.b MMUsave(a6),d0 ;get previous MMU state in d0 _rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2) SHOW MOVE.L SAVEA5(A6),A5 ;RESTORE A5 TST.B CRSRFLAG(A6) ;DID WE SHIELD THE CURSOR? BEQ.S GOHOME ;=>NO, JUST RETURN _SHOWCURSOR ;RESTORE CURSOR GOHOME BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped MOVE.L SAVESTK(A6),SP ;STRIP VARIABLE SIZED BUFFER move.l stackHandle(a6),d0 ;did we allocate a handle? beq.s @noTemp ;no, forget it. move.l d0,a0 ;pass handle in a0 _DisposeTempBuffer ;dispose it. move.l saveStkLowPt(a6),stkLowPt ;restart the sniffer <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 ; move.l d0,stackFree(a6) ; tst.l stackHandle(a6) ;have we been here before? bne.s @noMem ;yes, forget it. move.l HiHeapMark,oldHiHeapMark(a6) ;save extent of stack <09JUN92 SAH> moveq #4,d0 ; swap d0 ;try for 256K _NewTempBuffer ;returns a0=handle, d0=size move.l d0,d2 ;copy the actual size beq.s @noMem ;if zero, we didn't get it. @gotit move.l a0,stackHandle(a6) ;remember to dispose it later sub.l #qdStackXtra,d2 ;leave room for interrupts asr.l #2,d2 ;make cnt of longs add.l d2,stackFree(a6) ;new free cnt bmi.s @noMem ;didn't get enough clr.l stkLowPt ;disable stack sniffer move.l a7,a2 ;remember where save regs are move.l (a0),a0 ;get ptr exg a0,d0 ;get ptr in d0, size in a0 _rTranslate24To32 ;strip it move.l d0,HiHeapMark ;set up stack limit for _stackSpace add.l d0,a0 ;point to end of block move.l 7*4(a7),-(a0) ;copy over return address move.l a0,a7 ;move the stack there movem.l (a2),d0-d3/a0-a2 ;restore state rts @noMem move.w #nsStackerr,QDErr bra.s SHOW ;****************************************************************************************** ;-------------------------------------------- ; ; Source scanline merge routines. ; There are 3 routines: OneDeep, NDeep, and Average16and32 ; These routines copy from srcaddr to srcbuf and do vertical ; merging of source if necessary. ; ; When promoting source (ie dither mode) to 32 bit/pixel, Average16and32 ; is called. ; ; EXPECTS: D0: D1: D2: D3: ; D4: D5:!SRCALIGN D6:!DSTALIGN D7:!INVERTFLAG ; A0: A1: A2: A3: ; A4: A5: A6: A7: ;-------------------------------------------- VMergeTable dc.l oneDeep-VMergeTable ;src 1-bit/pixel dc.l ndeep-VMergeTable ;src 2-bit/pixel dc.l ndeep-VMergeTable ;src 4-bit/pixel dc.l ndeep-VMergeTable ;src 8-bit/pixel dc.l Average16and32-VMergeTable ;src 16-bit/pixel dc.l Average16and32-VMergeTable ;src 32-bit/pixel ;-------------------------------------------- ; ; Loop to combine d7 pixels of source and dest using mask ; ; ENTRY: ; D0: scratch A0: scratch ; D1: scratch A1: mask ptr ; D2: scratch A2: destination ; D3: scratch A3: src and dst ptr ; D4: scratch A4: src pmtable A5: rowbytes ; D5: srcAlign A5: rowbytes ; D6: realDepth (pixel size) ; D7: byte Count (zero based) ; ; There are 12 different cases: all combinations of source and mask ; being either 16- or 32-bits/pixel and dest being any depth. A mask ; of $ff means take source. The mask value ranges from 0-$7f,$81-$100. CombineTable ;SRC DST MASK ENTRY dc.l Combine32in32-CombineTable ;32 ind 32 0 dc.l Combine321632-CombineTable ;32 16 32 1 dc.l Combine323232-CombineTable ;32 32 32 2 ;******************************************************************* ; ; CombineMaskCase ; ; Loop to combine d7 pixels of source and dest using mask ; ;ENTRY: ; D0: (dst) A0: address of routine called ; D1: (src) A1: mask ptr ; D2: (dst component) A2: destination ; D3: (mask) A3: src and dst ptr ; D4: (build pixel) A4: src pmtable A5: rowbytes ; D5: srcAlign A5: ; D6: realDepth (pixel size) ; D7: byte Count (zero based) ; ; There are 12 different cases: all combinations of source and mask ; being either 16- or 32-bits/pixel and dest being any depth. A mask ; of $ff means take source. The mask value ranges from 0-$7f,$81-$100. ; ;EXIT: ; ; ;******************************************************************* ; ; handle merging with indexed destinations, assume source and mask are 32 bpp ; ; Promote destination pixel to 32-bits/pixel, combine with source on a ; component by component basis according to value stored in mask ; Combine32in32 bfextu (a2){d5:d6},d0 ;get a pixel of destination add d6,d5 ;bump to next pixel moveq #0,d4 move.w d4,d1 ;clear regs move.w d4,d2 move.w d4,d3 move.b 1(a3),d2 ;get red of source move.b ctTable+rgb+red(a4,d0.w*8),d1 ;get destination red into virgin reg sub.w d2,d1 ;red dst - red source move.b 1(a1),d3 ;get red mask bpl.s @1 addq #1,d3 ;make mask go from 0 to 256 @1 muls.w d3,d1 lsl.w #8,d2 ;src*256 add.w d2,d1 ;(dst-src)*mask+(src*256) move.w d1,d4 ;new red component (0000RRXX) ; ; now do green ; move.w #0,d1 ;clear regs move.w d1,d2 move.w d1,d3 move.b 2(a3),d2 ;get green of source move.b ctTable+rgb+green(a4,d0.w*8),d1 ;get destination green into virgin reg sub.w d2,d1 ;green dst - green src move.b 2(a1),d3 ;get green mask bpl.s @2 addq #1,d3 ;make mask go from 0 to 256 @2 muls.w d3,d1 ;(dst-src)*mask lsl.w #8,d2 ;src*256 add.w d2,d1 ;(dst-src)*mask+(src*256) lsr.w #8,d1 move.b d1,d4 ;move in green component (0000RRGG) ; ; now do blue ; move.w #0,d1 ;clear regs move.w d1,d2 move.w d1,d3 move.b 3(a3),d2 ;get blue of source move.b ctTable+rgb+blue(a4,d0.w*8),d1 ;get destination green into virgin reg sub.w d2,d1 ;blue dst - blue src move.b 3(a1),d3 ;get green mask bpl.s @3 addq #1,d3 ;make mask go from 0 to 256 @3 muls.w d3,d1 ;(dst-src)*mask lsl.w #8,d2 ;src*256 add.w d2,d1 ;(dst-src)*mask+(src*256) lsr.w #8,d1 lsl.l #8,d4 ;result = 00RRGG00 move.b d1,d4 ;move in blue component (00RRGGBB) MOVE.L d4,(A3)+ ;PUT A LONG TO SRCBUF addq #4,a1 ;bump to next mask DBRA D7,Combine32in32 ;LOOP FOR ALL LONGS rts ; ; Handle when src and mask are 32 bpp, dst is 16 bpp ; Combine321632 move.l maskBC,a0 ;get useful Konstantin Combine321632Loop move.l (a1)+,d5 ;get a pixel of mask bne.s @maskNonZero addq.l #4,a3 ;mask 0 -> all src so just skip addq.l #2,a2 ;bump destination dbra D7,Combine321632Loop ;LOOP FOR ALL LONGS rts @maskNonZero move.w (a2)+,d4 ;get a pixel of destination cmp.l d5,a0 ;mask $7FFF? beq @Writeout555 ;all dst, so write out d4 @DoSlowCase move.w d4,d0 ;copy destination pixel move.l (a3),d6 ;get a pixel of source moveq #0,d4 move.w d4,d1 ;clear regs move.w d4,d3 move.w d4,d2 swap d6 move.b d6,d2 ;get red of source swap d6 move.w d0,d4 ;red destination in 14 - 10 lsr.w #7,d4 ;move red to bits 7 - 3 and.w #$00f8,d4 ;strip bits 2 - 0 move.b d4,d3 lsr.b #5,d3 ;replicate top 3 bits or.b d3,d4 ;merge top five bits with top 3 bits sub.w d2,d4 ;red dst - red src swap d5 move.b d5,d3 ;get red mask bpl.s @1 addq #1,d3 ;make mask go from 0 to 256 @1 swap d5 muls.w d3,d4 ;d2=(dst-src)*mask asr.l #8,d4 ;(dst-src)*mask/256 add.l d2,d4 ;(dst-src)*mask/256+(src) swap d4 ;new red component (00RR0000) ; ; now do green ; move.w d6,d1 ;get green of source lsr.w #8,d1 ;get green in low byte move.w d0,d2 ;green destination in 9 - 5 lsr.w #2,d2 ;green in bits 7 - 3 and.w #$00f8,d2 ;strip bits 2 - 0 move.b d2,d3 lsr.b #5,d3 ;replicate top 3 bits or.b d3,d2 ;merge top five bits with top 3 bits sub.w d1,d2 ;green dst - green src move.w d5,d3 ;get green mask lsr.w #8,d3 tst.b d3 bpl.s @2 addq #1,d3 ;make mask go from 0 to 256 @2 muls.w d3,d2 ;d2 = (dst-src)*mask lsl.w #8,d1 ;src*256 add.w d1,d2 ;(dst-src)*mask+(src*256) move.w d2,d4 ;move in green component (00RRGGxx) ; ; now do blue ; move.w #0,d1 ;clear regs move.w d1,d3 move.b d6,d1 ;get blue of source move.b d0,d2 ;blue destination in 4 - 0 lsl.w #3,d2 ;green in bits 7 - 3 and.w #$00f8,d2 ;strip bits 2 - 0 move.b d2,d3 lsr.b #5,d3 ;replicate top 3 bits or.b d3,d2 ;merge top five bits with top 3 bits sub.w d1,d2 ;blue dst - blue src move.b d5,d3 ;get green mask bpl.s @3 addq #1,d3 ;make mask go from 0 to 256 @3 muls.w d3,d2 ;(dst-src)*mask lsl.w #8,d1 ;src*256 add.w d1,d2 ;(src-dst)*mask+(dst*256) lsr.w #8,d2 move.b d2,d4 ;move in blue component (00RRGGBB) @writeoutPixel move.l d4,(a3)+ ;PUT A LONG TO SRCBUF dbra D7,Combine321632Loop ;LOOP FOR ALL LONGS rts @Writeout555 ; ; d4 has pixel to write out in 555: convert to 888 and write it out ; moveq #0,d0 move.w d4,d0 ;red in 14-10 and.w #$7c00,d0 swap d0 ;red in 31-24 lsr.l #7,d0 ;red in 23-16 move.w d4,d0 ;green in 9-5 and.w #$03e0,d0 lsl.w #6,d0 ;green in 15-8 move.b d4,d0 ;blue in 4-0 and.b #$1f,d0 lsl.b #3,d0 ;blue in 7-0, green in 15-8, red in 23-16 move.l d0,d4 bra.s @writeoutPixel ; ; Handle when src, mask, dst all 32 bpp ; Combine323232 move.l maskBC,a0 ;get useful Konstantin Combine323232Loop move.l (a1)+,d5 ;get a pixel of mask bne.s @maskNonZero ;no, go the hard way addq.l #4,a3 ;yes, all src so just skip addq.l #4,a2 ;bump dst dbra D7,Combine323232Loop ;LOOP FOR ALL LONGS rts @maskNonZero move.l (a2)+,d4 ;get a pixel of destination cmp.l d5,a0 ;mask $00FFFFFF? beq.s @WriteoutPixel ;all dst, so write out d4 @DoSlowCase move.l d4,d0 ;copy destination pixel move.l (a3),d6 ;get a pixel of source moveq #0,d4 move.w d4,d1 ;clear regs move.w d4,d2 move.w d4,d3 swap d6 move.b d6,d2 ;get red of source swap d0 swap d6 move.b d0,d4 ;get a pixel of destination swap d0 sub.w d2,d4 ;red dst - red src swap d5 move.b d5,d3 ;get red mask bpl.s @1 addq #1,d3 ;make mask go from 0 to 256 @1 swap d5 muls.w d3,d4 asr.l #8,d4 ;(dst-src)*mask/256 add.l d2,d4 ;(dst-src)*mask/256+(src) swap d4 ;new red component (00RR0000) ; ; now do green ; move.w d6,d1 ;get green of source move.w d0,d2 ;get a pixel of destination lsr.w #8,d1 ;get green in low byte lsr.w #8,d2 ;get green in low byte sub.w d1,d2 ;green dst - green src move.w d5,d3 ;get green mask lsr.w #8,d3 tst.b d3 bpl.s @2 addq #1,d3 ;make mask go from 0 to 256 @2 muls.w d3,d2 ;(dst-src)*mask lsl.w #8,d1 ;src*256 add.w d1,d2 ;(dst-src)*mask+(src*256) move.w d2,d4 ;move in green component (00RRGGxx) ; ; now do blue ; move.w #0,d1 ;clear regs move.w d1,d2 move.w d1,d3 move.b d6,d1 ;get blue of source move.b d0,d2 ;get blue of destination sub.w d1,d2 ;blue dst - blue src move.b d5,d3 ;get green mask bpl.s @3 addq #1,d3 ;make mask go from 0 to 256 @3 muls.w d3,d2 ;(dst-src)*mask lsl.w #8,d1 ;src*256 add.w d1,d2 ;(src-dst)*mask+(dst*256) lsr.w #8,d2 move.b d2,d4 ;move in blue component (00RRGGBB) @writeoutPixel move.l d4,(a3)+ ;PUT A LONG TO SRCBUF dbra D7,Combine323232Loop ;LOOP FOR ALL LONGS rts ;********************************************************************* ; ; Loop to expand and merge D7 scanlines of indexed pixels ; ;ENTRY: ; D0: scratch A0: scratch ptr ; D1: scratch A1: scratch ptr ; D2: scratch A2: destination ; D3: scratch A3: source ; D4: src longs A4: src pmtable ; D5: srcAlign A5: rowbytes ; D6: realDepth (pixel size) ; D7: Scanline Count (zero based) ; ;EXIT: ; ; a3: new srcaddr ; ;GLOBALS: AvgBufPtr(a6), AvgBufSize(a6) ; ;********************************************************************* NDEEP ; LOOP FOR ALL LONGS IN SRC SCANLINE move.l a3,a0 ;point to source move.l a2,a1 ;point to destination move d4,d1 ;get count of longs @Align bfextu (a0){d5:0},d0 ;get an aligned long of source add #4,a0 ;bump to next long move.l d0,(a1)+ ;put a long to destination dbra d1,@Align ;loop for all longs ; add.l a5,a3 ;bump source to next row _pmVersion subq #1,d7 bpl.s @1 rts ; do verticle merging @1 move d6,d3 ;get pixel depth move.w d4,a4 ;save count of longs NdeepMerge move.l d7,-(sp) ;save count of lines to do move.l a3,a0 ;point to source move.l a2,a1 ;point to destination move a4,d6 ;get long count moveq #0,d4 ;start at beginning of long ndlong bfextu (a0){d5:0},d0 ;extract a long from source move.l (a1),d1 ;get next long from destination ndpxl bfextu d0{d4:d3},d2 ;get pixel from source bfextu d1{d4:d3},d7 ;get pixel from destination cmp.l d7,d2 ;which is greater? ble.s nochng ;only change if source is greater bfins d2,d1{d4:d3} ;replace pixel is destination NOCHNG add d3,d4 ;bump to next pixel within long and #$1f,d4 ;done with long? bne.s ndpxl ;no, keep looping add #4,a0 ;bump src offset move.l d1,(a1)+ ;write to destination dbra d6,ndlong ;repeat for all longs ; add.l a5,a3 ;add rowbytes to src pointer 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 lsl.l #8,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up green accumulation divu.w d7,d1 ;get green average move.b d1,d0 ;put in low byte of pixel lsl.l #8,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up blue accumulation divu.w d7,d1 ;get red average move.b d1,d0 ;put in low byte of pixel move.l d0,(a1)+ ;dump pixel into destination dbra d3,@hardWay ;loop for all src longs rts @useShift moveq #0,d0 ;zero alpha channel move.w (a0)+,d1 ;pick up red accumulation lsr.w #1,d1 ;get red average move.b d1,d0 ;put in low byte of pixel lsl.l #8,d0 ;make room for next component move.w (a0)+,d1 ;pick up green accumulation lsr.w #1,d1 ;get green average move.b d1,d0 ;put in low byte of pixel lsl.l #8,d0 ;make room for next component move.w (a0)+,d1 ;pick up blue accumulation lsr.w #1,d1 ;get red average move.b d1,d0 ;put in low byte of pixel move.l d0,(a1)+ ;dump pixel into srcBuf dbra d3,@useShift ;loop for all src longs rts ;-------------- Top of 16-bit average loop ----------------- ; Top of 16-bit scanline averaging loop ; d7 and word at top of stack is number of scanlines to merge ; NextAverageV16 ; ; loop for all longs in source scanline ; move.l a3,a0 ;get source address move.l AvrgBuf(A6),A1 ;point to accumulation buffer move d4,d5 ;get count of source moveq #0,d1 ;use for extending to word data moveq #0,d2 ;use for extending to word data moveq #0,d3 ;use for extending to word data ;------------------------------------------------------------------------ @NDLONG move.l (A0)+,D0 ;EXTRACT A LONG FROM SRC (2 pixels) move.b d0,d3 ;pick up blue component as a byte and.b #$1f,d3 lsr.l #5,d0 ;toss blue move.b d0,d2 ;pick up green component as a byte and.b #$1f,d2 lsr.l #5,d0 ;toss green move.b d0,d1 ;pick up red component as a word and.b #$1f,d1 add.w d1,(a1)+ ;accumulate red value add.w d2,(a1)+ ;accumulate green value add.w d3,(a1)+ ;accumulate blue value ; ; Do second pixel in long ; lsr.l #5+1,d0 ;move to second 16-bit pixel in long move.b d0,d3 ;pick up blue component as a byte and.b #$1f,d3 lsr.l #5,d0 ;toss blue move.b d0,d2 ;pick up green component as a byte and.b #$1f,d2 lsr.l #5,d0 ;toss green move.b d0,d1 ;pick up red component as a word and.b #$1f,d1 add.w d1,(a1)+ ;accumulate red value add.w d2,(a1)+ ;accumulate green value add.w d3,(a1)+ ;accumulate blue value dbra d5,@NDLONG ;repeat for all longs ; add.l a5,a3 ;bump source to next row _pmVersion dbra d7,NextAverageV16 ;loop while scan lines left move.w (a7)+,d7 ;retrieve # scanlines merged (0-based) addq #1,d7 ;make it 1 based ; Now we must compute the average of the accumulated R-G-B's move.l a2,a1 ;point to destination buffer move.l AvrgBuf(A6),A0 ;point to accumulation buffer move d4,d3 ;longs in source ; ; if it's a deep mask, we promote all 16-bit values to 32-bit ; move.w maskshift(a6),d0 cmp.w #4,d0 bge Promote16Loop cmp.w #2,d7 ;two scan lines merged? beq.s @useShift ;avoid division by using a shift @hardWay moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up red accumulation divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear) move.w d1,d0 ;put in low byte of pixel (only 6 bits count) lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up green accumulation divu.w d7,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up blue accumulation divu.w d7,d1 ;get red average or.b d1,d0 ;put in low byte of pixel ; ; Now do second pixel in long ; lsl.l #5+1,d0 ;bump to beginning of second pixel moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up red accumulation divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear) or.w d1,d0 ;put in low byte of pixel (only 5 bits count) lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up green accumulation divu.w d7,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up blue accumulation divu.w d7,d1 ;get red average or.b d1,d0 ;put in low byte of pixel swap d0 ;pixels mixed in AvrgBuf because of how constructed move.l d0,(a1)+ ;dump pixel into srcBuf dbra d3,@hardWay ;loop for all src longs rts @useShift move.w (a0)+,d1 ;pick up red accumulation lsr.b #1,d1 ;get red average move.w d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up green accumulation lsr.b #1,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up blue accumulation lsr.b #1,d1 ;get red average or.b d1,d0 ;put in low byte of pixel ; ; do second pixel (2/long in 16-bit mode) ; lsl.l #5+1,d0 move.w (a0)+,d1 ;pick up red accumulation lsr.b #1,d1 ;get red average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up green accumulation lsr.b #1,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up blue accumulation lsr.b #1,d1 ;get red average or.b d1,d0 ;put in low byte of pixel swap d0 move.l d0,(a1)+ ;dump pixel into srcBuf dbra d3,@useShift ;loop for all src longs rts Promote16Loop ; ; Average 16 bit values and put result back in AvrgBuf, then call ; Scale16to32 to promote to 32 bits ; move.l a0,a1 ;copy AvrgBuf ptr cmp.w #2,d7 ;two scan lines merged? beq.s @useShift ;avoid division by using a shift @hardWay moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up red accumulation divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear) move.w d1,d0 ;put in low byte of pixel (only 6 bits count) lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up green accumulation divu.w d7,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up blue accumulation divu.w d7,d1 ;get red average or.b d1,d0 ;put in low byte of pixel ; ; Now do second pixel in long ; lsl.l #5+1,d0 ;bump to beginning of second pixel moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up red accumulation divu.w d7,d1 ;get red average (alpha channel [bit 6] should be clear) or.w d1,d0 ;put in low byte of pixel (only 5 bits count) lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up green accumulation divu.w d7,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component moveq #0,d1 ;use for extending to word data move.w (a0)+,d1 ;pick up blue accumulation divu.w d7,d1 ;get red average or.b d1,d0 ;put in low byte of pixel swap d0 ;pixels mixed in AvrgBuf because of how constructed move.l d0,(a1)+ ;dump pixel into srcBuf dbra d3,@hardWay ;loop for all src longs bra.s @DoPromote @useShift move.w (a0)+,d1 ;pick up red accumulation lsr.b #1,d1 ;get red average move.w d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up green accumulation lsr.b #1,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up blue accumulation lsr.b #1,d1 ;get red average or.b d1,d0 ;put in low byte of pixel ; ; do second pixel (2/long in 16-bit mode) ; lsl.l #5+1,d0 move.w (a0)+,d1 ;pick up red accumulation lsr.b #1,d1 ;get red average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up green accumulation lsr.b #1,d1 ;get green average or.b d1,d0 ;put in low byte of pixel lsl.l #5,d0 ;make room for next component move.w (a0)+,d1 ;pick up blue accumulation lsr.b #1,d1 ;get red average or.b d1,d0 ;put in low byte of pixel swap d0 move.l d0,(a1)+ ;dump pixel into srcBuf dbra d3,@useShift ;loop for all src longs @DoPromote ; ; Call Scale16to32 to promote pixels to 32 bpp ; move.l AvrgBuf(A6),A0 ;pointer to source move.l a2,a1 ;pointer to destination lsl.l #3,d4 ;calc size of dst: ;longs to bytes and 16 bit to 32 bit = *8 <7JULY90 KON> add.l d4,a2 ;calc end of dst buffer 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 ; 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. ; 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! ; 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 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 CLR.W csStart(A1) ; start at zero, use sequence mode MOVE.W ctSize(A0),csCount(A1) ; for the length of the table LEA ctTable(A0),A0 ; get pointer to colorspecs MOVE.L A0,csTable(A1) ; color table pointer is first param 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 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 ; ; 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 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 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 @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 beq paramError ; if NIL, exit move.l d0,a0 ; 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. @@@@ ; 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 @@@@ 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 ; ; 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 btst #14,d3 ; are they palette references? bne brink ; yes call dave 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 @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 _Color2Index ; convert to index MOVE.L (SP)+,D0 ; get result move.l D0,TBLOFST(SP,D3*4) ; put returned value in table @@@@ 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 @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 _Color2Index ; convert to index MOVE.L (SP)+,D0 ; get result move.l D0,TBLOFST(SP,D3*4) ; put returned value in table @@@@ 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 MOVE.L (SP)+,D0 ; get result move.l D0,TBLOFST(SP,D3*4) ; put returned value in table @@@@ DBRA D4,@nxtPEntry ; => repeat until done clr.w QDErr ;remove any lingering error from ColorThing2Index ; ; 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) 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? @@@@ bne.s @findUnused ; if not, plow onward @@@@ 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 @@@@ 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. ;<<>> ; 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 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> 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 MOVE.L D5,D0 ;GET BYTECOUNT _NewHandle ;ALLOCATE BITS HANDLE BNE tryBands ;=> error, try a band at a time 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 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 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 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 <> _NEWPIXPAT ;get a new pixPat MOVE.L (SP)+,A0 ;get pixPat handle add.l ([PicSave,a3]),a4 ;offset into record <> 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 ;---------------------------------------------------- ; ; 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 if not(TheFuture) then ; <124> Need this for the present EntryTable CalcMask,$A838 ; CalcMask and SeedFill need to EntryTable SeedFill,$A839 ; always scan up as well as down 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 ; <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 ; <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 ; <69> ; MOVE.W #$ABA8,D0 MOVEQ #-120,D1 ;MOVEQ #%10001000,D1 (stupid assembler) LEA RAMstColorTab,A1 BSR TabPatcher8 ; ; Move scDirTab8 to RAM ; <69> ; MOVE.W #$ABB5,D0 MOVEQ #%00100000,D1 ;assembles because high bit is clear LEA RAMscDirTab8,A1 BSR TabPatcher8 ; ; Move stGrayTab to RAM ; <69> ; MOVE.W #$ABA9,D0 MOVEQ #-52,D1 ;MOVEQ #%11001100,D1 (again, stupid assembler) LEA RAMstGrayTab,A1 BSR TabPatcher8 ; ; Move bArith16Tab to RAM ; <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 ;--------------------------------------------------------- ; <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