mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-29 07:29:15 +00:00
cf23aad670
That is to day, put *something* in its place with the right length and symbol locations. Now we can be sure that no incorrect bytes are due to confused branch instructions, and therefore that they must all be fixed.
4431 lines
176 KiB
Plaintext
4431 lines
176 KiB
Plaintext
;
|
|
; File: GWorld.a
|
|
;
|
|
; Copyright: © 1981-1993 by Apple Computer, Inc.All rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM5> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
|
|
; so they can conditionalized out of the build.
|
|
; <SM4> 6/14/93 kc Roll in Ludwig.
|
|
; <LW2> 3/25/93 fau Made the NewGWorld call allocate a buffer whose width is a whole
|
|
; number of quadwords, in order to help digitizer grabs.
|
|
; <SM3> 10/28/92 SWC Replaced obsolete INCLUDEd filenames with their replacements.
|
|
; <SM2> 6/11/92 stb <sm 6/9/92>stb Synch with QDciPatchROM.a; added comments to
|
|
; NewGWorld, UpdateGWorld, Pixmap32Bit, GetGWorldPixMap,
|
|
; OffscreenVersion. Added a missing ENDPROC
|
|
; <26> 8/23/91 JSM Remove benign redefinition of TRUE and FALSE, which are now
|
|
; defined by the build script.
|
|
; <25> 4/30/91 dba change to use standard system equates for public interface (got
|
|
; rid of the extra copy of the off-screen interface in this file)
|
|
; <24> 1/14/91 KON Fix more problems in UpdateGWorld having to do with GWorld
|
|
; flags. [SMC]
|
|
; <23> 12/14/90 KON Fix bug in UpdateGWorld where the wrong flags are returned.
|
|
; [smc]
|
|
; <22> 11/26/90 SMC Fixed the way grafvars were getting resized. With BAL.
|
|
; <21> 10/31/90 SMC Fixed alpha channel bugs with BAL.
|
|
; <20> 9/17/90 BG Removed <14>. 040s are now behaving more reliably.
|
|
; <19> 9/16/90 KON Change OffscreenVersNum to 130 for 7.0. Gestalt will then return
|
|
; 230 on color machines.
|
|
; <18> 9/7/90 KON Check for wide open rectangular regions in mapRgn rather than
|
|
; here and pictures.a.
|
|
; <17> 9/5/90 KON Don't call map region if region is wide open.
|
|
; <16> 7/24/90 gbm get rid of branches to nowhere
|
|
; <15> 7/11/90 gbm get rid of some assembly warnings
|
|
; <14> 6/26/90 BG Added EclipseNOPs to deal with flakey 040s.
|
|
; <13> 6/21/90 KON When specifying noNewDevice to NewGWorld, the depth should be
|
|
; taken from the device.
|
|
; <12> 6/8/90 dba oops...the last change made buffers that were too small; must
|
|
; calculate buffer sizes for NewScreenBuffer from actual
|
|
; off-screen rectangle, since we donÕt add the extra slop for
|
|
; realignment
|
|
; <11> 6/8/90 dba Fix bug where we tried to dispose handles but put them in d0
|
|
; instead of a0. Also fix bug that I introduced in change <3>
|
|
; where pixmaps would be created too narrow because we moved the
|
|
; right as well as the left coordinate when aligning the pixmap.
|
|
; <10> 6/5/90 KON Do error checking after calling GetMaxDevice in
|
|
; NewGWorld, UpdateGWorld, and NewTempScreenBuffer.
|
|
; <9> 5/22/90 KON Fix UpdateGWorld so it doesn't look at the Disposed GWorld or
|
|
; its GrafVars.
|
|
; <8> 3/28/90 DVB GetGWorldPixMap never worked right at all.
|
|
; <7> 2/13/90 BAL Changed Offscreen version from $102 to $120.
|
|
; <6> 2/1/90 DAF Update PixMap32Bit to honor the new GDFlag for devices accessed
|
|
; in 32-bit mode.
|
|
; <5> 1/17/90 KON Changed compare so GetGWorldPixMap (selector 23) can be
|
|
; selected.
|
|
; <4> 1/17/90 BAL Added the GetGworldPixmap selector for compatibility with
|
|
; classic machines
|
|
; <3> 12/28/89 dba donÕt allocate 31 pixels for slop in NewScreenBuffer; there is
|
|
; no UpdateScreenBuffer, so the slop wasnÕt helping; also fix a
|
|
; bug in NewScreenBuffer: the bottom right was not slid over when
|
|
; aligning, so the bounds of the pixMap would be open a bit too
|
|
; wide
|
|
; <2> 12/27/89 dba shorten by a few bytes; (Boy was it worth it!)
|
|
; <1.8> 11/8/89 BAL Added the routine Pixmap32Bit as selector 22.
|
|
; <1.7> 9/25/89 BAL Conditionalized includes for system 7.0 builds
|
|
; <1.6> 8/23/89 BAL Altered UGW to 'OR' (not MOVE) clip/stretch bit into result.
|
|
; <1.5> 8/15/89 dba save port around OpenCPort so that NewGWorld does not change
|
|
; thePort; also use ClosePort instead of CloseCPort Õcause itÕs
|
|
; much better
|
|
; <1.4> 7/16/89 DAF FOR AURORA BUILD - Rolled in a MultiFinder-related change for
|
|
; Jean-Charles
|
|
; <¥1.3> 7/14/89 BAL For Aurora: Final CQD
|
|
; <1.2> 6/30/89 BAL Removed "END" directive from tail of file. Fixed UpdateGWorld
|
|
; bugs.
|
|
; <1.1> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
|
|
; file (colorequ.a), got rid of QuickDraw nFiles dependencies and
|
|
; fixed up necessary filesÉ
|
|
; <1.0> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
|
|
;
|
|
; To Do:
|
|
; donÕt allocate 31 pixels of slop all the time; the real thing is 32-pixelSize bytes of slop
|
|
;
|
|
|
|
STRING ASIS
|
|
|
|
MACHINE MC68020
|
|
|
|
FruFru Proc Export ; bogus proc to close off any open procs from previous files
|
|
ENDPROC
|
|
|
|
;----------------------------------------------------------------------------
|
|
; The following constants are used in conditional assembly to produce the best suited
|
|
; version of Quickdraw Extensions depending on the context.
|
|
; 1. If QD Extensions are assembled independently of 32-bit Quickdraw, set UseTranslate24To32 to 0
|
|
; 2. To produce a version that can be reinstalled without rebooting, set DontReinstall to 0
|
|
; (if running under MultiFinder, also set UseSetTrapAddress to 0).
|
|
; 3. Until we run with a Graphics Accelerator, AsyncQD should be set to 0.
|
|
; 4. If boot time becomes an issue, set UseLessMemory to 0 (installation will be twice as fast).
|
|
; 5. If QD Extensions are put in ROM, and we don't want to override it with the version on disk,
|
|
; set DontReinstall to 1.
|
|
;
|
|
; FOR A DEBUGGING VERSION, SET THE FOLLOWING CONSTANTS TO (1,1,0,1,0,0).
|
|
; FOR A DEBUGGING VERSION INDEPENDENT OF 32-BIT QD, USE (0,0,0,1,0,0).
|
|
; FOR A BUILD, USE (1,1,1,1,1,0).
|
|
;
|
|
UseTranslate24To32 equ 1 ; 1=use Translate24To32, 0=use StripAddress
|
|
UsePaletteMgr equ 1 ; 1=use Palette Mgr calls, 0=use regular Quickdraw calls
|
|
UseSetTrapAddress equ 1 ; 1=install with SetTrapAddress, 0=store directly in ToolTable
|
|
UseLessMemory equ 1 ; 1=installation takes less memory/more time, 0=more memory/less time
|
|
DontReinstall equ 1 ; 1=don't reinstall QDExtensions if already installed, 0=override previous version
|
|
AsyncQD equ 0 ; true if Asynchronous Quickdraw present
|
|
|
|
separatePTCH equ 0 ; true if not part of a greater build
|
|
|
|
OffscreenVersNum equ $130 ; version 1.3 (System 7.0) of the quickdraw extensions
|
|
|
|
IF separatePTCH THEN
|
|
|
|
; Some other constants
|
|
|
|
QDExtTrapNum equ $31D ; trap number for Quickdraw Extensions
|
|
ToolTable equ $e00 ; start of toolbox dispatch table
|
|
nuRBMask equ $7fff ; mask used to strip rowBytes flags
|
|
|
|
IF (&TYPE('_CopyMask') = 'UNDEFINED') THEN
|
|
INCLUDE 'QuickDraw.a'
|
|
INCLUDE 'fasttraps.a'
|
|
INCLUDE 'colorequ.a'
|
|
INCLUDE 'qdHooks.a'
|
|
INCLUDE 'Palettes.a'
|
|
|
|
INCLUDE 'QDExtEqu.a'
|
|
INCLUDE 'QDExtPrivEqu.a'
|
|
ENDIF
|
|
|
|
|
|
ELSE ;FORROM
|
|
|
|
|
|
INCLUDE 'QDOffscreen.a'
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; 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
|
|
|
|
ENDIF ;NOT FORROM
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Extensions to Quickdraw for 32-bit Quickdraw and Graphics Accelerators
|
|
;
|
|
; This file consists of:
|
|
;
|
|
; 1. Offscreen Graphics Environments
|
|
; NewGWorld: create an offscreen graphics world
|
|
; GetGWorld: get the current graphics world
|
|
; SetGWorld: set the current graphics world
|
|
; UpdateGWorld: adapt the graphics world to new depth, alignment, etc.
|
|
; DisposeGWorld: dispose of the graphics world
|
|
; LockPixels: lock the offscreen buffer (call before calling Quickdraw)
|
|
; UnlockPixels: unlock the offscreen buffer after drawing is finished
|
|
; AllowPurgePixels: make offscreen buffer purgeable
|
|
; NoPurgePixels: make offscreen buffer unpurgeable
|
|
; GetPixelsState: return the lock and purge state of the offscreen buffer
|
|
; SetPixelsState: set the lock and purge state of the offscreen buffer
|
|
; GetPixBaseAddr: waits until Async QD is done and return a 32-bit pointer to the offscreen buffer
|
|
; GetGWorldDevice: returns the attached device to an offscreen GWorld.
|
|
; NewScreenBuffer: allocates only an offscreen pixmap
|
|
; DisposeScreenBuffer: diposes of an offscreen pixmap.
|
|
;
|
|
; 2. Asynchronous Quickdraw
|
|
; PortChanged: notifies Quickdraw of any non-procedural changes to a port
|
|
; PixPatChanged: notifies Quickdraw of any non-procedural changes to a pixpat
|
|
; CTabChanged: notifies Quickdraw of any non-procedural changes to a color table
|
|
; GDeviceChanged: notifies Quickdraw of any non-procedural changes to a gDevice
|
|
;
|
|
; 3. Utilities
|
|
; GetMaxAreaDevice: find device with largest overlapping area with a given rectangle
|
|
; FindInverseTable: find an already built inverse table for a given color table in the device list
|
|
; QDDone: becomes true when the pending Quickdraw calls on a given port are completed
|
|
; BitMapDone: becomes true when the pending Quickdraw calls on a given pixmap are completed
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
; THINGS TO DO:
|
|
;
|
|
; 1.Some of the same code is used in three different routines (NewGWorld, UpdateGWorld,
|
|
; and NewScreenBuffer). Rearchitect it to use subroutines.
|
|
;
|
|
; 2.Make GetMaxAreaDevice smarter and actually use it. GetMaxAreaDevice could estimate
|
|
; the break-even performance point between unaligned CopyBits and CopyBits
|
|
; with color mapping in terms of surface area and decide between which device
|
|
; to align the pixmap to.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; MODIFICATIONS
|
|
;
|
|
; 10Mar89 JCM Started today in SEG, Jean-Charles Mourey.
|
|
; 11Mar89 JCM Wrote NewGWorld, GetMaxAreaDevice, SetGWorld, GetGWorld,
|
|
; UpdateGWorld, QDDone, PortChanged, PixPatChanged, CTabChanged,
|
|
; LoMemChanged.
|
|
; 13Mar89 JCM Added LockPixels and UnlockPixels. Modified CTabChanged to create
|
|
; a new seed.
|
|
; 15Mar89 JCM Added support for cTable=-1 (no offscreen device). Now avoid calling
|
|
; time-consuming MakeITable to create inverse table when inverse table
|
|
; already exists in a device somewhere. Added FindInverseTable.
|
|
; 16Mar89 JCM Added Patch installer and dispatch code. This file is ptch ID=37 in
|
|
; 32-bit Quickdraw. Added dummy color table and inverse table in direct
|
|
; device (for compatibility).
|
|
; 17Mar89 JCM Added flag bits as result of UpdateGWorld.
|
|
;
|
|
; ** ALPHA CANDIDATE **
|
|
;
|
|
; 23Mar89 JCM Major changes. Introduced GWorldPtr type. Changed interface to
|
|
; NewGWorld, UpdateGWorld, DisposeGWorld, LockPixels. Added flags parameter.
|
|
; Added purgeable option for offscreen buffer. Changed functionalities of
|
|
; LockPixels and UnlockPixels. They must now be called before and after calling
|
|
; Quickdraw on an offscreen graphics world. Added AllowPurgePixels,
|
|
; NoPurgePixels, GetPixelsState, SetPixelsState, GetPixBaseAddr.
|
|
; Added an "e" to DisposGWorld. Removed link a6, unlk a6 when possible.
|
|
; Fixed bug in NewGWorld in disposOffscreenHandles. Introduced pmVersion=2
|
|
; to signal a handle in the baseAddr. pmVersion=1 means the baseAddr is
|
|
; a 32-bit pointer. The dummy ctSeed in 16 and 32 bits/pixel is now
|
|
; cmpCnt*cmpSize.
|
|
; 24Mar89 JCM Now set correctly offscreenGWorld's portVersion. Fixed crash bug in
|
|
; DisposeGWorld when disposing offscreen device. Changed all routines that
|
|
; access the baseAddr so that they work whether baseAddr is a handle or a
|
|
; pointer (LockPixels, UnlockPixels, AllowPurgePixels, NoPurgePixels,
|
|
; GetPixBaseAddr, DisposeGWorld). Added GetGWorldDevice. Now make offscreen
|
|
; buffer unpurgeable in LockPixels and restore purge state in UnlockPixels.
|
|
; Use high bit of pmVersion to remember purge state (this conflicts with
|
|
; 32-bit Quickdraw's fAddr32clean but pmVersion=1 already tells 32-bit QD
|
|
; that the baseAddr is 32-bit clean, so it should be no problem. Any better
|
|
; solution?). AllowPurgePixels and NoPurgePixels now change only the isPurgeable
|
|
; bit (in pmVersion), actual setting of the handle purge state is done in
|
|
; UnlockPixels (Quickdraw doesn't like drawing to purged offscreen buffer!).
|
|
; Changed GetPixelsState to get purge state from pmVersion. Changed SetPixelsState
|
|
; to set lock and purge state with Lock/UnlockPixels and Allow/NoPurgePixels to
|
|
; be consistent. Changed QDDone to take a port as a parameter, make it
|
|
; a trap (QDDone might or might not make it in final release). Added BitMapDone
|
|
; (equivalent of QDDone with a bit/pixmap). BitMapDone is called by QDDone and
|
|
; GetPixBaseAddr. Don't use high bit of pmVersion anymore; it turns out that
|
|
; a locked handle can't be purged (dummy me!)
|
|
; 25Mar89 JCM Rewrote UpdateGWorld to match new interface.
|
|
; 26Mar89 JCM Fixed many bugs in UpdateGWorld (too many to list). Added error code checking.
|
|
; Changed SetPixelsState to use Lock/UnlockPixels and Allow/NoPurgePixels instead
|
|
; (HAPPY EASTER!) of HSetState to avoid problem of making the offscreen buffer unlocked and
|
|
; purgeable when the baseAddr is a pointer. Added NewScreenBuffer and
|
|
; DisposeScreenBuffer.
|
|
; 27Mar89 JCM Fixed stack offset bug in GetPixBaseAddr.
|
|
;
|
|
; ** FIRST BETA CANDIDATE **
|
|
;
|
|
; 28Mar89 JCM Now make offscreen pixmap bounds 1 pixel more than necessary so that we can always
|
|
; realign the pixmap in UpdateGWorld. Fixed bugs in computing UpdateGWorld's result.
|
|
; Accurately set the newRowBytesBit and reallocPixBit. Optimized UpdateGWorld in the
|
|
; case the pixels are purged, but nothing else has changed. Restore the previous
|
|
; current graphics world upon exit of UpdateGWorld.
|
|
; 29Mar89 JCM Added direct optimized color mapping in UpdateGWorld, in case only the color table
|
|
; changes (use MakeScaleTbl and check for identity mapping).
|
|
; 30Mar89 JCM Fix many bugs in UpdateGWorld's new code. Fixed bug in FindInverseTable,
|
|
; it returned the last screen gdevice's inverse table if it didn't find any.
|
|
; Changes after Code Review: Changed cParmErr to paramErr. Definition
|
|
; of mapPixMask, newDepthMask, alignPixMask, newRowBytesMask, and reallocPixMask
|
|
; was wrong (by one 0). In QDExtensions.h, changed argument types Rect *
|
|
; to const Rect *. Added definitions for pixelsLockedBit, pixelsPurgeableBit, and
|
|
; their masks. Changed isGWorld to isGWorldMask. Added definitions for PixMapVers1,
|
|
; PixMapVers2, srcAverage, nil, true, and false. Now check for presence of QD
|
|
; Extensions and doesn't reinstall if present (e.g. if it's in ROM already).
|
|
; Optimized routine dispatcher. Don't use GetMaxAreaDevice anymore until I figure
|
|
; out a really smart way to use it. Save less registers on the stack. Allocate
|
|
; the CGrafPort in low memory (ResrvMem) rather than high memory (MoveHHi). Don't
|
|
; compare d0 with noErr upon return from a Memory Manager routine. Fixed bug in
|
|
; computation of leg room in rowBytes for possible realignment in UpdateGWorld
|
|
; (Thanks, Chris!). Fixed bug where if cloning the color table failed, the
|
|
; museDevice's inverse table got disposed of! Report Memory Manager errors without
|
|
; change. Use rtd instructions to exit all routines. Fixed a bug where the port
|
|
; didn't get closed if SetHandleSize of its grafVars failed. In GetGWorld and SetGWorld,
|
|
; get and set the port directly from the Quickdraw Globals (no GetPort, SetPort).
|
|
; Now reset current device to MainDevice in SetGWorld if the port is not a GWorldPtr
|
|
; and the device is NIL. Now use pea instructions instead of lea and move -(sp).
|
|
; In UpdateGWorld, if error in GetCTable, try to find where the error happened
|
|
; (Quickdraw, Memory Manager, or Resource Manager) and return correct error. Use
|
|
; conditional compilation to remove BitMapDone and simplify QDDone and GetPixBaseAddress
|
|
; if Asynchronous Quickdraw is not present (which is the case until we get a Graphics
|
|
; Accelerator). Clarify comments for LockPixels and UnlockPixels. Don't use bufPtr
|
|
; as a local variable in GetPixBaseAddr (conflict with low-mem global bufPtr).
|
|
; 31Mar89 JCM Added constants for conditional assembly: UseTranslate24To32, UseSetTrapAddress,
|
|
; UseLessMemory, DontReinstall, AsynQD. Added definitions for ToolTable, QDExtTrapNum.
|
|
; Added an alternative algorithm to install QD Extensions that takes more time
|
|
; but less memory. Changed long branches to short branches whenever possible.
|
|
; Optimize error checking at beginning of UpdateGWorld (use mask instead of bclr).
|
|
; Use an optimized algorithm in UpdateGWorld if the pixels just need to be realigned.
|
|
; Fixed bug in UpdateGWorld where the pixels would sometimes be preserved even if
|
|
; not desired. Fixed bug in UpdateGWorld where a derefenced pointer to grafVars
|
|
; was used after MakeITable. Fixed bug in optimized color mapping (one long too many!).
|
|
; Fixed bug in GetPixBaseAddr due to changing bufPtr to bufResult (see above) .
|
|
; Fixed bug in fast realignment algorithm in UpdateGWorld, the alignment offset
|
|
; was in pixels instead of bits.
|
|
; 1Apr89 JCM "FINAL" version (no kidding...)
|
|
;
|
|
; ** "FINAL" **
|
|
;
|
|
; 3Apr89 JCM When running out of memory, fixed bug where port was sometimes closed even if
|
|
; it hadn't been opened. In UpdateGWorld, do a better job at restoring old gworld
|
|
; if NewGWorld fails (reallocate the old offscreen buffer).
|
|
; 4Apr89 JCM Changed interface to Lock/UnlockPixels, Allow/NoPurgePixels, Set/GetPixelsState,
|
|
; and GetPixBaseAddr (use BitMap/PixMap/portBits parameter instead of PixMapHandle)
|
|
; 5Apr89 JCM Changed interface back to PixMapHandle (sorry, Darin...). In dispatcher,
|
|
; function selector now contains the size of the parameters in the high word
|
|
; (except for functions 0 through 19 for compatibility). A paramErr is returned
|
|
; in case of unimplemented function and the stack is cleaned up correctly.
|
|
; 7Apr89 JCM Now preserves the clipRgn during an UpdateGWorld (as well as the pixpats,
|
|
; grafVars, grafProcs, RGB fore/background colors, pen and text characteristics,
|
|
; packType, packSize, hRes, vRes, searchProcs, compProcs, and other misc fields).
|
|
;
|
|
; ** SECOND BETA CANDIDATE **
|
|
;
|
|
; 10Apr89 JCM Fixed color table seed bug in UpdateGWorld (always compute seed as long). Be
|
|
; more clever in copying the clipRgn across UpdateGWorld, map clipRgn to new
|
|
; portRect if stretching requested, offset it if clipping requested.
|
|
; 13Apr89 JCM In UpdateGWorld, check whether the port's pixpats are NIL before calling CopyPixPat
|
|
; (because DisposPixPat clears all references to the pixpat in all ports and CopyPixPat
|
|
; doesn't like NIL PixPatHandles).
|
|
; 14Apr89 JCM Fixed crash bug in SetPixelsState when lock bit is set.
|
|
; 25Apr89 JCM Now use Palette Manager SaveFore, RestoreFore, SaveBack, RestoreBack in
|
|
; UpdateGWorld to update the RGB color and color indices in the port and
|
|
; grafVars in a way that's compatible with the Palette Manager.
|
|
; 26Apr89 JCM UpdateGWorld doesn't do anything if there is nothing to do at all
|
|
; (for those who call UpdateGWorld all the time). SaveFore doesn't work
|
|
; (waiting for the Palette Manager fix).
|
|
; 27Apr89 JCM In UpdateGWorld:
|
|
; Save and Restore current GWorld before using Palette Manager (SaveFore
|
|
; is now fixed). If savePort or saveDevice are the same as the old port
|
|
; or old attached device, replace them with the new port and new attached
|
|
; device. Now set the newGWorld's clipRgn to portRect before CopyBits and
|
|
; restore it afterwards. Update the RGB color and color indices in the port
|
|
; in the optimized case where only the color table changes.
|
|
; 28Apr89 JCM Use Quickdraw calls instead of Palette Manager calls to update RGB colors
|
|
; and color indices if 32-Bit Quickdraw Palette Manager is not present.
|
|
;
|
|
; ** SHIPPING AT DEVELOPER'S CONFERENCE (5/11/89) **
|
|
;
|
|
; 18May89 JCM Now preserve a2 in FindInverseTable.
|
|
; 23May89 JCM Cancel change to FindInverseTable. Now preserve a2 across NewGWorld,
|
|
; UpdateGWorld, and NewScreenBuffer.
|
|
; 26May89 JCM In UpdateGWorld, fixed grafProcs problem (don't dereference NIL grafProcs). Now
|
|
; copies the grafProcs pointer instead of the grafProcs structure (NOTE: the grafProcs record
|
|
; is not owned by the port).
|
|
; 28May89 BAL Always return error in both register d0 and QDErr.
|
|
; 28May89 BAL Included as part of the ROM build. Added FORROM conditionals.
|
|
; 19Jun89 JCM Fix alignment bug in UpdateGWorld. When updating only color table in UpdateGWorld, dispose
|
|
; of old inverse table before replacing it by new one.
|
|
; 20Jun89 JCM In UpdateGWorld's check for identity mapping, clear upper-half of d1 (used as long offset).
|
|
; 21Jun89 JCM Added new function OffscreenVersion to get the version number of the installed QD extensions.
|
|
; Version number is defined as a constant at the beginning of this file.
|
|
; 21Jun89 JCM NewGWorld now returns error codes also in d0 and QDErr. UpdateGWorld returns result (>=0 or <0)
|
|
; also in d0, and errors are also returned in QDErr (if result >=0, QDErr is set to 0).
|
|
; 06Jul89 BAL When reallocating purged pixels, use ReallocHandle instead of NewHandle. Added useMFTempBit
|
|
; flag to NewGWorld as a new option to allocate pixels in MultiFinder Temp Memory. Defined
|
|
; new pmVersion for 32-bit pointer baseAddr. Updated GetPixBaseAddr to handle all pmVersions.
|
|
; 07Jul89 JCM Added new flag to grafVars structure (useMFTemp) to remember that the pixels are in
|
|
; MultiFinder memory. Modified UpdateGWorld to take it into account. Changed interface to
|
|
; NewScreenBuffer: purgeable Boolean changed to 16-bit flags containing purgePixBit and useMFTempBit.
|
|
; It is possible to allocate pixels in MF temp memory with NewScreenBuffer.
|
|
;
|
|
; ** 14Jul89: BASTILLE DAY -- BICENTENNIAL OF THE FRENCH REVOLUTION!!! **
|
|
;
|
|
; 14Jul89 JCM Changed interface to NewScreenBuffer back to original for compatibility. Added new call:
|
|
; NewTempScreenBuffer to allocate pixels in MultiFinder temp memory.
|
|
; 16Jul89 JCM Correctly set grafVars' useMFTemp flag in NewGWorld.
|
|
;----------------------------------------------------------------------------
|
|
|
|
|
|
IF separatePTCH THEN
|
|
|
|
InstallQDExtensions PROC EXPORT
|
|
IMPORT QDExtDispatcher, QDExtEnd
|
|
;----------------------------------------------------------------------------
|
|
; Patch installer.
|
|
; The Quickdraw Extensions are a patch resource (SysHeap, Locked) loaded by
|
|
; 32-bit Quickdraw at boot time.
|
|
; This code installs the _QDExtensions trap vector in the trap dispatch table.
|
|
; If the code is already installed, don't reinstall it (don't overwite it if
|
|
; it is in ROM).
|
|
; NOTE: When a future version of QDExtensions comes around, this will be
|
|
; changed to override a possible ROM version.
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Get handle to the resource containing this code
|
|
|
|
lea InstallQDExtensions,a0 ; get address of this resource
|
|
_RecoverHandle ; find the handle to it
|
|
move.l a0,-(sp) ; save it on the stack
|
|
|
|
if DontReinstall then
|
|
|
|
; Check if we're installed already
|
|
|
|
move #QDExtTrapNum,d0 ; get trap number for Quickdraw extensions
|
|
_GetTrapAddress ,NEWTOOL ; get the address of the trap (it's a toolbox trap)
|
|
move.l a0,-(sp) ; save it on the stack
|
|
|
|
move #UnimplementedTrap,d0 ; get trap number of the Unimplemented trap
|
|
_GetTrapAddress ,NEWTOOL ; get the address of the trap
|
|
cmp.l (sp)+,a0 ; are both addresses the same?
|
|
beq.s installTheDamnThing ; yes, install Quickdraw Extensions
|
|
|
|
; Quickdraw Extensions are already installed (probably in ROM)
|
|
; Get rid of this version and quit
|
|
|
|
_ReleaseResource ; get rid of this resource
|
|
rts ; and quit
|
|
|
|
endif
|
|
|
|
; Install Quickdraw Extensions
|
|
; Detach the resource so we'll stay in System Heap forever.
|
|
|
|
installTheDamnThing
|
|
|
|
; The following algorithm uses less memory. The patch is loaded in
|
|
; application heap and the code (less the installation code) is moved
|
|
; to system heap.
|
|
|
|
if UseLessMemory then
|
|
|
|
lea QDExtEnd,a1 ; get address of end of code
|
|
lea QDExtDispatcher,a0 ; get address of beginning of code
|
|
sub.l a0,a1 ; get size of code
|
|
move.l a1,d0 ; get size in d0 for NewHandle
|
|
move.l d0,-(sp) ; save size on stack
|
|
_NewHandle ,SYS ; allocate a handle in system heap
|
|
_HLock ; lock it
|
|
move.l (a0),a1 ; get pointer
|
|
move.l (sp)+,d0 ; get size saved on stack
|
|
move.l a1,-(sp) ; save pointer to new area in system heap
|
|
|
|
lea QDExtDispatcher,a0 ; source pointer
|
|
_BlockMove ; a1 contains destination and d0 contains size
|
|
|
|
; Install ourselves in trap dispatch table
|
|
|
|
move.l (sp)+,d0 ; get pointer to beginning of code
|
|
_StripAddress ; get a 32-bit clean address
|
|
|
|
; Two different ways to install the Quickdraw Extensions Trap:
|
|
; 1. Use SetTrapAddress
|
|
; 2. Direct store in Tool Table
|
|
;
|
|
; Method 1 is the recommended method, but doesn't work if we're installed
|
|
; after MultiFinder (which I do a lot for debugging purposes)
|
|
|
|
if UseSetTrapAddress then
|
|
move.l d0,a0 ; put address in a0 for NSetTrapAddress
|
|
move #QDExtTrapNum,d0 ; put trap number in d0 for NSetTrapAddress
|
|
_SetTrapAddress ,NEWTOOL ; install trap in trap table
|
|
else
|
|
move.l #ToolTable+(QDExtTrapNum*4),a1 ; get address of trap table entry
|
|
move.l d0,(a1) ; make it point to our dispatcher
|
|
endif
|
|
|
|
; Get rid of loaded resource
|
|
|
|
_ReleaseResource ; get rid of resource
|
|
|
|
rts
|
|
|
|
; This alternative installation algorithm minimizes the installation time.
|
|
; The patch is loaded directly in System Heap by the Resource Manager
|
|
; and the resource is detached.
|
|
|
|
else
|
|
|
|
_DetachResource ; detach this resource from resource file (handle is on stack)
|
|
|
|
; Install ourselves in trap dispatch table
|
|
|
|
lea QDExtDispatcher,a0 ; get address of the dispatcher
|
|
move.l a0,d0 ; get address in d0 for StripAddress
|
|
_StripAddress ; get a 32-bit clean address
|
|
|
|
; Two different ways to install the Quickdraw Extensions Trap:
|
|
; 1. Use SetTrapAddress
|
|
; 2. Direct store in Tool Table
|
|
;
|
|
; Method 1 is the recommended method, but doesn't work if we're installed
|
|
; after MultiFinder (which I do a lot for debugging purposes)
|
|
|
|
if UseSetTrapAddress then
|
|
move.l d0,a0 ; put address in a0 for NSetTrapAddress
|
|
move #QDExtTrapNum,d0 ; put trap number in d0 for NSetTrapAddress
|
|
_SetTrapAddress ,NEWTOOL ; install trap in trap table
|
|
else
|
|
move.l #ToolTable+(QDExtTrapNum*4),a1 ; get address of trap table entry
|
|
move.l d0,(a1) ; make it point to our dispatcher
|
|
endif
|
|
|
|
rts ; and that's it!
|
|
|
|
endif
|
|
|
|
ENDPROC
|
|
|
|
ENDIF ;NOT FORROM
|
|
|
|
|
|
QDExtDispatcher PROC EXPORT
|
|
IMPORT NewGWorld, LockPixels, UnlockPixels, UpdateGWorld, DisposeGWorld
|
|
IMPORT GetGWorld, SetGWorld, CTabChanged, PixPatChanged, PortChanged
|
|
IMPORT GDeviceChanged, AllowPurgePixels, NoPurgePixels, GetPixelsState
|
|
IMPORT SetPixelsState, GetPixBaseAddr, NewScreenBuffer, DisposeScreenBuffer
|
|
IMPORT GetGWorldDevice, QDDone, OffscreenVersion,NewTempScreenBuffer,Pixmap32Bit
|
|
IMPORT GetGWorldPixMap
|
|
;----------------------------------------------------------------------------
|
|
; 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
|
|
jmp dispatchTable(d0*4) ; jump in jump table
|
|
|
|
dispatchTable
|
|
jmp NewGWorld ; selector 0
|
|
jmp LockPixels ; selector 1
|
|
jmp UnlockPixels ; selector 2
|
|
jmp UpdateGWorld ; selector 3
|
|
jmp DisposeGWorld ; selector 4
|
|
jmp GetGWorld ; selector 5
|
|
jmp SetGWorld ; selector 6
|
|
jmp CTabChanged ; selector 7
|
|
jmp PixPatChanged ; selector 8
|
|
jmp PortChanged ; selector 9
|
|
jmp GDeviceChanged ; selector 10
|
|
jmp AllowPurgePixels ; selector 11
|
|
jmp NoPurgePixels ; selector 12
|
|
jmp GetPixelsState ; selector 13
|
|
jmp SetPixelsState ; selector 14
|
|
jmp GetPixBaseAddr ; selector 15
|
|
jmp NewScreenBuffer ; selector 16
|
|
jmp DisposeScreenBuffer ; selector 17
|
|
jmp GetGWorldDevice ; selector 18
|
|
jmp QDDone ; selector 19
|
|
jmp OffscreenVersion ; selector 20
|
|
jmp NewTempScreenBuffer ; selector 21
|
|
jmp Pixmap32Bit ; selector 22 as seen in QDciPatchROM.a <sm 6/9/92>stb
|
|
jmp GetGWorldPixMap ; selector 23 as seen in QDciPatchROM.a <sm 6/9/92>stb
|
|
|
|
exit move.l (sp)+,a0 ; get return address
|
|
swap d0 ; get size of parameters in low word
|
|
ext.l d0 ; convert to long
|
|
adda.l d0,sp ; get rid of parameters
|
|
move #paramErr,d0 ; return parameter error
|
|
move d0,QDErr ; copy error code to low-memory global QDErr <29May89> BAL
|
|
jmp (a0) ; and return to callerz
|
|
|
|
ENDPROC
|
|
|
|
;Êas seen in QDciPatchROM.a <sm 6/9/92>stb
|
|
|
|
NewGWorld PROC EXPORT
|
|
IMPORT FindInverseTable
|
|
EXPORT ShiftTable
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION NewGWorld (VAR offscreenGWorld: GWorldPtr; pixelDepth: INTEGER;
|
|
; boundsRect: Rect; cTable: CTabHandle; aGDevice:GDHandle;
|
|
; flags: LONGINT): QDErr;
|
|
;
|
|
; Creates an offscreen graphics world, including an offscreen port,
|
|
; an offscreen pixmap, an offscreen buffer, and an optional offscreen device.
|
|
;
|
|
; offscreenGWorld is an output. It is set to a pointer to a CGrafPort
|
|
; with an expanded grafVars substructure. A reference to the offscreen device
|
|
; is put in the grafVars record. If no offscreen device is created, a reference
|
|
; to aGDevice is put in the grafVars record. In both cases, the device is called
|
|
; the attached device.
|
|
;
|
|
; The pixelDepth can be 0,1,2,4,8,16,or 32.
|
|
; If the pixelDepth is 0:
|
|
; The boundsRect is interpreted as a global rectangle in screen space.
|
|
; The depth and color table of the deepest device intersecting
|
|
; with boundsRect is used for the offscreen graphics environment.
|
|
; The port's portRect is set to the same size as boundsRect with the topLeft
|
|
; coordinates set to (0,0).
|
|
; The pixmap's bounds is set to the smallest rectangle enclosing portRect and aligned
|
|
; to the greatest overlapping device with boundsRect (this is to optimize CopyBits
|
|
; between offscreen and screen).
|
|
; The device's gdRect is copied from the pixmap's bounds.
|
|
; If the pixelDepth is 1,2,4,8,16,or 32:
|
|
; The pixmap's bounds, portRect, and device's rect are all set to boundsRect.
|
|
;
|
|
; If pixelDepth is zero, cTable is ignored. Otherwise:
|
|
; If cTable is not nil, it is used as the device and port's color table.
|
|
; If cTable is nil, the default color table for pixelDepth is used
|
|
;
|
|
; Flags contain 2 flag bits:
|
|
; pixPurgeBit = allocate a purgeable offscreen buffer
|
|
; noNewDeviceBit = don't create an offscreen device.
|
|
;
|
|
; If noNewDeviceBit is clear, aGDevice is ignored.
|
|
; If noNewDeviceBit is set, aGDevice is used as the attached device.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; 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
|
|
gDevFlags 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,
|
|
|
|
move.l offscreenGWorld(a6),a0
|
|
clr.l (a0)
|
|
|
|
;-------------------------------------------------------------------------
|
|
; 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 flags in d3
|
|
|
|
move.l gDevFlags(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
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Treat 24-bit color as 32-bit.
|
|
|
|
cmp #24,d7
|
|
bne.s @dontSetTo32
|
|
moveq #32,d7
|
|
@dontSetTo32
|
|
|
|
;-------------------------------------------------------------------------
|
|
; 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 paramError ; if aGDevice is NIL, report a parameter error
|
|
move.l d0,museDevice(a6) ; if not NIL, use it as muse Device
|
|
bra.s GetPixelDepthFromDevice ; take the pixel depth from the museDevice <KON 21JUN90>
|
|
@0
|
|
bra.s checkPixelShift ; skip next part and check pixel resolution
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If pixelDepth is 0, use boundsRect as a rectangle in global screen space
|
|
; to find deepest device that intersects that rectangle.
|
|
|
|
findMaxDevice
|
|
clr.l -(sp) ; leave room for GDHandle result
|
|
move.l boundsRect(a6),-(sp) ; pass boundsRect as a global rectangle in screen space
|
|
_GetMaxDevice ; find deepest device that intersects boundsRect
|
|
move.l (sp)+,d0 ; get max device handle <KON 5Jun90>
|
|
beq paramError ; check for NIL handle <KON 5Jun90>
|
|
move.l d0,a0 ; <KON 5Jun90>
|
|
move.l a0,museDevice(a6) ; use this device as our new source of inspiration
|
|
|
|
;-------------------------------------------------------------------------
|
|
; For maximum efficiency when copying offscreen pixmap to screen, try
|
|
; to match the pixel alignment of the offscreen pixmap to the pixel
|
|
; alignment of the portion of screen space described by boundsRect.
|
|
|
|
computeAlignment
|
|
|
|
; First step: compute horizontal offset between boundsRect and muse device
|
|
|
|
move.l (a0),a0 ; get pointer to device
|
|
move.l boundsRect(a6),a1 ; get pointer to boundsRect
|
|
move left(a1),d0 ; get left coordinate of boundsRect
|
|
sub gdRect+left(a0),d0 ; subtract left coordinate of device rectangle
|
|
move d0,horizOffset(a6) ; save offset
|
|
|
|
; Second step: convert boundsRect to local coordinates (topLeft = 0, 0)
|
|
|
|
move right(a1),d0 ; compute boundsRect->right - boundsRect->left
|
|
sub left(a1),d0
|
|
move d0,localRect+right(a6) ; store in localRect.right
|
|
move bottom(a1),d0 ; compute boundsRect->bottom - boundsRect->top
|
|
sub top(a1),d0
|
|
move d0,localRect+bottom(a6) ; store in localRect.bottom
|
|
clr.l localRect+topLeft(a6) ; set localRect.top and localRect.left to 0
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If pixelDepth = 0 or noNewDeviceBit is set, we get the pixel resolution
|
|
; from the museDevice
|
|
|
|
GetPixelDepthFromDevice
|
|
move.l ([museDevice,a6]),a0 ; get pointer to museDevice
|
|
move.l ([gdPMap,a0]),a1 ; get pointer to its pixmap
|
|
move pmPixelSize(a1),d7 ; d7 = pixel resolution to use
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Convert pixel depth to shift amount.
|
|
; pixelShift = log2(pixelDepth). If pixelShift is not integer, pixelShift is invalid.
|
|
; Use a conversion table that is valid for integers from 0 to 32
|
|
; Table returns 0,1,2,3,4 or -1 if pixelDepth is not a power of 2.
|
|
|
|
checkPixelShift
|
|
lea ShiftTable,a0 ; table to convert pixelDepth to pixelShift (exponent of 2)
|
|
moveq #0,d0 ; clear high byte
|
|
move.b 0(a0,d7),d0 ; fetch table
|
|
bmi badPixelDepth ; if table returned -1, pixelDepth is invalid, exit w/error
|
|
|
|
move d0,pixelShift(a6) ; save exponent in pixelShift
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Calculate pixmap bounds.
|
|
; Take into account the horizontal offset. The horizontal offset represents
|
|
; the number of unused pixels at the beginning at each line of the offscreen
|
|
; pixmap, so that the offscreen pixmap is aligned to the screen.
|
|
; The horizontal offset has a meaning only when pixelDepth = 0.
|
|
|
|
move localRect+top(a6),pixmapBounds+top(a6) ; pixmapBounds.top = localRect.top
|
|
|
|
; Convert horizOffset to a number of bits modulo 32 and
|
|
; offset pixmapBounds.left with the equivalent number of pixels.
|
|
|
|
move horizOffset(a6),d1 ; get horizontal offset in pixels
|
|
lsl d0,d1 ; convert to bits
|
|
and #$1f,d1 ; offset modulo 32
|
|
lsr d0,d1 ; convert back to pixels
|
|
|
|
move localRect+left(a6),d0 ; pixmapBounds.left = localRect.left - pixelOffset
|
|
sub d1,d0
|
|
move d0,pixmapBounds+left(a6) ; store in pixmapBounds
|
|
|
|
move.l localRect+botRight(a6),pixmapBounds+botRight(a6) ; bottom and right coordinates unchanged
|
|
|
|
;-------------------------------------------------------------------------
|
|
; 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
|
|
;
|
|
; size of the buffer is:
|
|
; rowBytes * (pixmapBounds.bottom - pixmapBounds.top)
|
|
|
|
allocateBuffer
|
|
move localRect+right(a6),d0 ; get right coordinate
|
|
sub localRect+left(a6),d0 ; compute number of pixels per line
|
|
ext.l d0 ; convert to long
|
|
move pixelShift(a6),d1 ; get shift amount for this pixel resolution
|
|
lsl.l d1,d0 ; convert pixels to bits
|
|
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
|
|
|
|
; Make buffer's width quad longword aligned on both ends. This will help when doing
|
|
; video digitizer grabs on Cyclone.
|
|
|
|
addi.l #15,d0 ; Add 15 bytes to make it to the next quad-w boundary <LW2>fau
|
|
andi.b #$f0,d0 ; Chop the remainder <LW2>fau
|
|
|
|
move d0,bytesPerRow(a6) ; save # of bytes in a row
|
|
|
|
move localRect+bottom(a6),d1 ; compute height of rectangle
|
|
sub localRect+top(a6),d1 ; bottom-top
|
|
mulu.w d1,d0 ; compute height * rowBytes
|
|
|
|
btst.l #useTempMemBit,d3 ; use MF temp memory? (d3 contains the flags)
|
|
beq.s @useCurHeap ; no, allocate in current heap
|
|
_NewTempHandle ; allocate it in Juggler heap, returns actual size in D0
|
|
tst.l d0 ; is it empty?
|
|
bne.s @gotMem ; no, got the memory <07Jul89> JCM
|
|
move #cTempMemErr,d0 ; yes, report error <07Jul89> JCM
|
|
bra reportError ; <07Jul89> JCM
|
|
|
|
@useCurHeap
|
|
_NewHandle ; allocate offscreen buffer (don't initialize it)
|
|
bne reportError ; if Memory Manager error, report it and quit
|
|
|
|
@gotMem move.l a0,offscreenBufH(a6) ; save handle to offscreen buffer
|
|
|
|
_MoveHHi ; move the buffer as high as possible in memory
|
|
|
|
; If purgePixBit is set, make the offscreen buffer purgeable
|
|
|
|
btst.l #purgePixBit,d3 ; is purgePixBit set? (d3 contains the flags)
|
|
beq.s @0 ; no, leave as is
|
|
_HPurge ; yes, make it purgeable
|
|
@0
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Get inverse table resolution from the inspiration gDevice's preferred resolution
|
|
|
|
move.l ([museDevice,a6]),a0 ; get pointer to muse device
|
|
move gdResPref(a0),resPref(a6) ; save preferred resolution for later
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Create the offscreen PixMap.
|
|
; This pixmap will be used for the offscreen device and offscreen port.
|
|
; The baseAddr is a handle to the offscreen buffer.
|
|
; IMPORTANT: the pmVersion field is set to 2.
|
|
; pmVersion = PixMapVers2 means that the baseAddr is a handle.
|
|
; pmVersion = PixMapVers1 means that the baseAddr is a 32-bit pointer.
|
|
|
|
createPixMap
|
|
moveq #pmRec,d0 ; get size of PixMap structure
|
|
_NewHandle ,CLEAR ; allocate the handle
|
|
bne reportError ; if Memory Manager error, report it and quit
|
|
|
|
move.l a0,offscreenPixMap(a6) ; save it
|
|
move.l (a0),a1 ; a1 = pixmap pointer
|
|
|
|
; Start filling out the fields of the pixmap
|
|
|
|
move.l offscreenBufH(a6),pmBaseAddr(a1) ; store HANDLE to offscreen buffer in pixmap
|
|
move bytesPerRow(a6),d0 ; get # of bytes in a row
|
|
or #pmFlag,d0 ; flag pixmap as being a Color Quickdraw pixmap
|
|
move d0,pmRowBytes(a1) ; store rowBytes and pixmap flag in pixmap
|
|
move.l pixmapBounds+topLeft(a6),pmBounds+topLeft(a1) ; copy pixmapBounds to pixmap's bounds
|
|
move.l pixmapBounds+botRight(a6),pmBounds+botRight(a1)
|
|
move #PixMapVers2,pmVersion(a1) ; IMPORTANT: set pixmap's version to PixMapVers2 (baseAddr is a handle)
|
|
move #72,pmHRes(a1) ; hRes = 72.0 in fixed format
|
|
move #72,pmVRes(a1) ; vRes = 72.0 in fixed format
|
|
|
|
move d7,pmPixelSize(a1) ; store d7 (pixelDepth) in pixmap
|
|
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Note: Some fields will not be initialized. They remain set to 0. Those
|
|
; fields are: packType, packSize, planeBytes, pmReserved.
|
|
|
|
;-------------------------------------------------------------------------
|
|
; The remaining fields of the pixmap are determined differently whether
|
|
; the pixel depth is 1,2,4,8 or 16,32.
|
|
|
|
cmp #16,d7 ; if pixel depth < 16,
|
|
blt.s clutPixels ; do things the classic way
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If the pixel depth is 16 or 32, device and pixel characteristics are:
|
|
;
|
|
; device type = direct type
|
|
; pixel type = RGB chunky direct (16)
|
|
; pixel size = 16 or 32
|
|
; component count = 3 (R,G,B)
|
|
; component size = 5 or 8
|
|
; color Table = none (dummy color table)
|
|
; inverse table = none (dummy inverse table)
|
|
|
|
move #directType,devType(a6) ; remember device type for later
|
|
move #16,pmPixelType(a1) ; pixelType = RGB chunky direct
|
|
move #3,pmCmpCount(a1) ; cmpCount = 3
|
|
moveq #8,d0 ; assume component size = 8 (32 bits/pixel)
|
|
cmp #32,d7 ; depth = 32 bits/pixel?
|
|
beq.s @0 ; yes, cmpSize = 8
|
|
moveq #5,d0 ; no, cmpSize = 5
|
|
@0 move d0,pmCmpSize(a1) ; store cmpSize in pixmap
|
|
|
|
btst.l #$1,d3
|
|
beq.s @skipthisnonsense
|
|
move.l ([museDevice,a6]),a0
|
|
move.l ([gdPMap,a0]),a0
|
|
move.l gdMode(a0),a0
|
|
move.l a0,offscreenCTable(a6)
|
|
move.l ([offscreenPixMap,a6]),a1
|
|
move.l a0,gdMode(a1)
|
|
bra createDevice
|
|
@skipthisnonsense
|
|
|
|
; Create an empty color table.
|
|
|
|
move #ctRec,d0 ; size of an empty color table
|
|
_NewHandle ,CLEAR ; allocate it
|
|
bne reportError ; if Memory Manager error, report it and quit
|
|
|
|
move.l a0,offscreenCTable(a6) ; save handle to dummy color table
|
|
move.l ([offscreenPixMap,a6]),a1 ; get pointer to offscreen pixmap
|
|
move.l a0,pmTable(a1) ; store handle to dummy color table in pixmap
|
|
|
|
move.l (a0),a0 ; get pointer to dummy color table
|
|
|
|
; Set the color table seed to cmpCount * cmpSize (3*8 in 32 bits/pixel, 3*5 in 16 bits/pixel)
|
|
|
|
moveq #3*8,d0 ; assume 32 bits/pixel (cmpCount=3, cmpSize=8)
|
|
cmp #32,d7 ; is depth = 32 bits/pixel?
|
|
beq.s @1 ; yes, seed = 3 * 8
|
|
moveq #3*5,d0 ; no, seed = 3 * 5
|
|
@1 move.l d0,ctSeed(a0) ; store seed in color table
|
|
|
|
; Create a dummy inverse table (doesn't have to be a seed)
|
|
|
|
moveq #2,d0 ; small handle for dummy inverse table
|
|
_NewHandle ,CLEAR ; allocate it
|
|
bne reportError ; if Memory Manager error, report it and quit
|
|
|
|
move.l a0,offscreenITable(a6) ; save handle to dummy inverse table
|
|
|
|
bra createDevice ; go create offscreen device
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If the pixel depth is 1,2,4,or 8, device and pixel characteristics are:
|
|
;
|
|
; device type = clut type
|
|
; pixel type = chunky (0)
|
|
; pixel size = 1,2,4,or 8
|
|
; component count = 1
|
|
; component size = pixel size
|
|
; color table = cloned from provided color table or museDevice
|
|
; inverse table = built from the color table
|
|
|
|
clutPixels
|
|
move #clutType,devType(a6) ; remember device type for later
|
|
move #0,pmPixelType(a1) ; pixelType = chunky
|
|
move #1,pmCmpCount(a1) ; 1 component (the pixel index)
|
|
move d7,pmCmpSize(a1) ; cmpSize = pixelSize
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If noNewDeviceBit is set, share color table with museDevice and don't create an offscreen device.
|
|
; If no color table is provided, copy color table from the muse device or
|
|
; get it from the system file.
|
|
; If the caller has provided its own color table, clone it.
|
|
|
|
move.l cTable(a6),a0 ; color table handle
|
|
|
|
; Try to get the inverse table from the museDevice if possible
|
|
; Keep handle to inverse table in a4 until we get to clone it.
|
|
; This is because we don't want to deallocate the museDevice's inverse table
|
|
; if an error occurs in cloning the color table!
|
|
|
|
move.l #nil,a4 ; initialize handle to inverse table (in a4)
|
|
|
|
; If noNewDeviceBit is set, share color table with museDevice and skip device creation part
|
|
|
|
btst.l #noNewDeviceBit,d3 ; is noNewDeviceBit set? (d3 contains the flags)
|
|
beq.s checkPixelDepth ; no, look at pixel depth
|
|
|
|
; Get color table handle from museDevice and store it in the offscreenPixMap
|
|
|
|
move.l ([museDevice,a6]),a0 ; get the master pointer to the device
|
|
move.l ([gdPMap,a0]),a0 ; get the master pointer to its pixmap
|
|
move.l pmTable(a0),a0 ; get the color table handle
|
|
move.l a0,offscreenCTable(a6) ; save it
|
|
move.l ([offscreenPixMap,a6]),a1 ; get pointer to offscreen pixmap
|
|
move.l a0,pmTable(a1) ; store handle to color table in pixmap
|
|
|
|
bra initPort ; go directly to port initialization, skip device stuff
|
|
|
|
; If pixelDepth = 0, ignore cTable, copy color table from museDevice
|
|
|
|
checkPixelDepth
|
|
tst pixelDepth(a6) ; is pixelDepth 0?
|
|
beq.s getFromMuse ; yes, get color table from museDevice
|
|
|
|
; 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?
|
|
bne.s dontCloneCTab ; yes, this a copy already, don't clone it
|
|
|
|
; If pixelDepth = 0 or if getting the default color table failed,
|
|
; get color table and inverse table from our inspiration gDevice
|
|
|
|
getFromMuse
|
|
move.l ([museDevice,a6]),a0 ; get the master pointer to the device
|
|
move.l gdITable(a0),a4 ; get its inverse table handle and keep it in a4
|
|
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,offscreenCTable(a6) ; save cloned color table handle
|
|
|
|
move.l ([offscreenPixMap,a6]),a1 ; get pointer to offscreen pixmap
|
|
move.l a0,pmTable(a1) ; store handle to cloned color table in pixmap
|
|
|
|
;-------------------------------------------------------------------------
|
|
; 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 in a4 (from museDevice), just clone it.
|
|
|
|
move.l a4,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 offscreenCTable(a6),-(sp) ; push handle to color table
|
|
jsr 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,offscreenITable(a6) ; save handle to inverse table
|
|
|
|
; Build Inverse Table
|
|
|
|
move.l offscreenCTable(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 reportError ; report error and quit
|
|
|
|
bra.s createDevice ; go create 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,offscreenITable(a6) ; save handle to cloned inverse table
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Create the offscreen device.
|
|
; Don't call NewGDevice to avoid allocating the offscreen device in the
|
|
; system heap.
|
|
; Don't allocate expanded cursor data and mask because this device is not
|
|
; a screen device.
|
|
; Uninitialized fields remain set to 0. Those fields are:
|
|
; gdRefNum: this device has no driver
|
|
; gdID: initially set to 0
|
|
; gdSearchProc: initially set to 0
|
|
; gdCompProc: initially set to 0
|
|
; gdRefCon
|
|
; gdNextGD: this device is not in the device list (should it?)
|
|
; gdCCBytes: no cursor on a non-screen device
|
|
; gdCCDepth: idem
|
|
; gdCCXData: idem
|
|
; gdCCXMask: idem
|
|
; gdReserved: must be 0
|
|
;
|
|
; NOTE: This part is skipped if noNewDeviceBit is set.
|
|
|
|
createDevice
|
|
|
|
btst.l #noNewDeviceBit,d3 ; is noNewDeviceBit set? (d3 contains the flags)
|
|
bne.s initPort ; yes, then we don't want an offscreen device
|
|
|
|
; Allocate memory for gDevice structure
|
|
|
|
moveq #gdRec,d0 ; get size of gDevice structure
|
|
_NewHandle ,CLEAR ; allocate the handle
|
|
bne reportError ; if Memory Manager error, report it and quit
|
|
|
|
move.l a0,offscreenDevice(a6) ; save handle to offscreen device
|
|
move.l (a0),a0 ; get pointer to device
|
|
|
|
; Fill in the fields of the gDevice
|
|
|
|
move devType(a6),gdType(a0) ; set device type to previously computed value
|
|
move.l offscreenITable(a6),gdITable(a0) ; store handle to inverse table
|
|
move resPref(a6),gdResPref(a0) ; set device preferred resolution as determined earlier
|
|
|
|
move #(1<<noDriver),d0 ; set device flags to noDriver
|
|
|
|
; Set device flags to color, except if pixel depth = 1 bit/pixel (=> monochrome)
|
|
|
|
cmp #1,d7 ; is depth 1 bit/pixel?
|
|
beq.s @0 ; yes, leave device flags as is
|
|
or #(1<<gdDevType),d0 ; no, set color bit in flags
|
|
@0 move d0,gdFlags(a0) ; store device flags
|
|
|
|
move.l offscreenPixMap(a6),gdPMap(a0) ; store handle to pixmap
|
|
|
|
move.l pixmapBounds+topLeft(a6),gdRect+topLeft(a0) ; copy pixmapBounds to device's gdRect
|
|
move.l pixmapBounds+botRight(a6),gdRect+botRight(a0)
|
|
|
|
move.l #-1,gdMode(a0) ; set mode to -1
|
|
|
|
; From now on, use the offscreen device as our museDevice
|
|
|
|
move.l offscreenDevice(a6),museDevice(a6)
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Initialize the offscreen port.
|
|
; The port is made to represent accurately the characteristics of the
|
|
; offscreen device (pixmap, color table, etc.)
|
|
|
|
initPort
|
|
|
|
; Set current device to museDevice before initializing offscreen port
|
|
; At this point, museDevice is the offscreen device. If no offscreen
|
|
; device was created (cTable=-1), museDevice is the current device.
|
|
|
|
move.l theGDevice,saveDevice(a6) ; save current device
|
|
move.l museDevice(a6),theGDevice ; set muse device as current
|
|
|
|
move.l GrafGlobals(a5),a0 ; get address of Quickdraw Globals <1.5>
|
|
move.l thePort(a0),-(sp) ; set the current port <1.5>
|
|
|
|
move.l offscreenPort(a6),-(sp) ; push address of offscreen port
|
|
_OpenCPort ; initialize port structure
|
|
|
|
move.l GrafGlobals(a5),a0 ; get address of Quickdraw Globals <1.5>
|
|
move.l (sp)+,thePort(a0) ; set the current port <1.5>
|
|
|
|
move.l saveDevice(a6),theGDevice ; restore current device
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If noNewDeviceBit is set, the portPixMap was copied from the current device,
|
|
; which is wrong. Dispose of that pixmap and replace it with the offscreen
|
|
; pixmap.
|
|
|
|
btst.l #noNewDeviceBit,d3 ; is noNewDeviceBit set? (d3 contains the flags)
|
|
beq.s computePortRect ; no, don't mess with portPixMap
|
|
|
|
; Dispose of the portPixMap without disposing of its color table (which
|
|
; is owned by the muse device).
|
|
|
|
move.l offscreenPort(a6),a0 ; get pointer to offscreen port
|
|
move.l portPixMap(a0),a0 ; push portPixMap handle
|
|
_DisposHandle ; and dispose of it
|
|
|
|
; Use the offscreen PixMap created earlier as the offscreen port's PixMap
|
|
|
|
move.l offscreenPixMap(a6),a0 ; get handle to offscreen PixMap
|
|
move.l offscreenPort(a6),a1 ; get pointer to offscreen port
|
|
move.l a0,portPixMap(a1) ; store offscreenPixMap handle in port's portPixMap
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Set the portRect field of the GrafPort to localRect,
|
|
; Note that:
|
|
; if pixelDepth is 0:
|
|
; localRect = boundsRect offset so that topLeft = (0,0)
|
|
; if pixelDepth is non 0:
|
|
; localRect = boundsRect
|
|
|
|
computePortRect
|
|
move.l offscreenPort(a6),a1 ; get pointer to offscreen port
|
|
move.l localRect+topLeft(a6),portRect+topLeft(a1) ; copy localRect to portRect
|
|
move.l localRect+botRight(a6),portRect+botRight(a1)
|
|
|
|
; Set visible region of offscreen port to portRect
|
|
|
|
move.l visRgn(a1),-(sp) ; push handle to visRgn
|
|
pea portRect(a1) ; push address of portRect
|
|
_RectRgn ; make visRgn = portRect
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Store in the grafVars substructure a reference to the offscreen device
|
|
; (or muse device if no offscreen device) and some flags.
|
|
|
|
; Expand the grafVars substructure to the size of the extended grafVars record
|
|
;Êas seen in QDciPatchROM.a at RectRgn come-from patch <sm 6/9/92>stb
|
|
|
|
move.l offscreenPort(a6),a0 ; get pointer to offscreen port
|
|
MOVE.L grafVars(A0),-(SP) ; push handle to grafvars <21>
|
|
_ResizeGrafVars ; set grafvars to extended size <21>
|
|
|
|
; 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
|
|
|
|
; Remembers whether we created the attachDevice or not.
|
|
|
|
moveq #true,d0 ; assume we created it
|
|
btst.l #noNewDeviceBit,d3 ; is noNewDeviceBit set? (d3 contains the flags)
|
|
beq.s @0 ; no, we created the device
|
|
moveq #false,d0 ; yes, we didn't create it
|
|
@0 move.b d0,devOwned(a0) ; store it in grafVars
|
|
|
|
; Remembers whether the pixels were allocated in MultiFinder temp memory or not <07Jul89> JCM
|
|
|
|
moveq #false,d0 ; assume not in temp memory <07Jul89> JCM
|
|
btst.l #useTempMemBit,d3 ; use MF temp memory? (d3 contains the flags) <07Jul89> JCM
|
|
beq.s @1 ; no, allocated in current heap <07Jul89> JCM
|
|
moveq #true,d0 ; yes, in MF temp memory <16Jul89> JCM
|
|
@1 move.b d0,useMFTemp(a0) ; store it in grafVars <07Jul89> JCM
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Mark the offscreen port as being a GWorld.
|
|
|
|
move.l offscreenPort(a6),a0 ; get pointer to offscreen port
|
|
or #isGWorldMask,portVersion(a0) ; set isGWorld bit in portVersion
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Store the offscreen port in the GWorldPtr variable
|
|
|
|
move.l offscreenGWorld(a6),a0 ; get pointer to offscreen GWorld variable
|
|
move.l offscreenPort(a6),(a0) ; store in it the pointer to the offscreen port
|
|
|
|
;-------------------------------------------------------------------------
|
|
; We're done. Return error code and put a copy of it in low-memory QDErr.
|
|
|
|
goHome move result(a6),d0 ; copy error code to d0 <21Jun89> JCM
|
|
ext.l d0 ; make d0 a long <21Jun89> JCM
|
|
move d0,QDErr ; copy error code to low-memory global QDErr <21Jun89> JCM
|
|
movem.l (sp)+,d3-d7/a2-a4 ; restore regs
|
|
unlk a6 ; get rid of stack frame
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
;-------------------------------------------------------------------------
|
|
; When an error occurs, all allocated memory is freed and an error code
|
|
; is returned.
|
|
|
|
badPixelDepth
|
|
move #cDepthErr,result(a6) ; pixel depth invalid
|
|
bra.s disposOffscreenHandles ; release memory and exit
|
|
|
|
paramError
|
|
move #paramErr,result(a6) ; one of the parameters is invalid
|
|
bra.s disposOffscreenHandles ; release memory and exit
|
|
|
|
reportError
|
|
move d0,result(a6) ; directly report Memory Manager error
|
|
|
|
; Dispose of all allocated memory (handle is allocated when non zero)
|
|
; If the port has been opened, close it and then dispose of the actual port structure
|
|
|
|
disposOffscreenHandles
|
|
|
|
move.l offscreenBufH(a6),a0 ; get handle to offscreen buffer
|
|
_DisposHandle ; dispose it
|
|
move.l offscreenPixMap(a6),a0 ; get handle to offscreen pixmap
|
|
_DisposHandle ; dispose it
|
|
move.l offscreenCTable(a6),a0 ; get handle to offscreen color table
|
|
_DisposHandle ; dispose it
|
|
move.l offscreenDevice(a6),a0 ; get handle to offscreen device
|
|
_DisposHandle ; dispose it
|
|
move.l offscreenITable(a6),a0 ; get handle to offscreen inverse table
|
|
_DisposHandle ; dispose it
|
|
move.l offscreenPortH(a6),d7 ; get handle to offscreen port
|
|
beq.s goHome ; if nil, don't do anything
|
|
move.l d7,a0 ; if not nil, check if the port has been opened
|
|
move.l (a0),a0 ; get pointer to port
|
|
move portVersion(a0),d0 ; get portVersion
|
|
and #cPortFlag,d0 ; check if cPortFlag set
|
|
cmp #cPortFlag,d0 ; is it set?
|
|
bne.s @0 ; if not set, don't close port
|
|
move.l (a0),-(sp) ; push pointer to port
|
|
_ClosePort ; close it down
|
|
@0
|
|
move.l d7,a0 ; get handle to offscreen port
|
|
_DisposHandle ; dispose it
|
|
bra.s goHome ; exit
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
; ShiftTable converts integers from 0 to 32 into their base 2 logarithm.
|
|
;
|
|
; Input: integers from 0 to 32
|
|
; Output: if input = 2^n, output = n
|
|
; otherwise, output = -1
|
|
;
|
|
ShiftTable dc.b -1,0,1,-1,2,-1,-1,-1
|
|
dc.b 3,-1,-1,-1,-1,-1,-1,-1
|
|
dc.b 4,-1,-1,-1,-1,-1,-1,-1
|
|
dc.b -1,-1,-1,-1,-1,-1,-1,-1,5
|
|
|
|
ENDPROC
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Currently don't use GetMaxAreaDevice in NewGWorld, UpdateGWorld, and
|
|
; NewScreenBuffer because if it doesn't have the same depth and color table
|
|
; as the deepest device intersecting the boundsRect, all performance gain
|
|
; will be lost. I could make GetMaxAreaDevice smarter.
|
|
|
|
|
|
if 0 then
|
|
|
|
GetMaxAreaDevice PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION GetMaxAreaDevice (globalRect: Rect): GDHandle;
|
|
;
|
|
; Find the device that has the largest overlapping area with globalRect.
|
|
; Take into account only active screen devices in device list.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; A6 offsets of parameters after link:
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
maxAreaDevice equ paramSize+8 ; LONG, GDHandle result
|
|
globalRect equ maxAreaDevice-4 ; LONG, pointer to globalRect
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; A6 offsets of local variables after link:
|
|
;
|
|
|
|
intersection equ -8 ; Rect, intersection of device and globalRect
|
|
varSize equ intersection ; size of local variables
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
link a6,#varSize ; allocate local variables
|
|
movem.l a2-a4/d3,-(sp) ; save regs
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Go through device list and find maximum overlap device
|
|
|
|
moveq #0,d3 ; initial overlap area
|
|
moveq #nil,a2 ; initial greatest overlapping device
|
|
|
|
move.l DeviceList,a3 ; start at beginning of device list
|
|
tst.l a3 ; is there a device (there should, really!)
|
|
beq exit ; exit if no device
|
|
|
|
deviceLoop
|
|
move.l (a3),a0 ; get pointer to device
|
|
move gdFlags(a0),d0 ; get device flags
|
|
btst #screenDevice,d0 ; is device a screen device?
|
|
beq nextDevice ; no, go to next device
|
|
btst #screenActive,d0 ; is device an active screen?
|
|
beq nextDevice ; no, go to next device
|
|
|
|
clr.b -(sp) ; leave room for boolean result
|
|
move.l globalRect(a6),-(sp) ; push globalRect
|
|
pea gdRect(a0) ; push address of device rectangle
|
|
pea intersection(a6) ; push address of intersection rectangle
|
|
_SectRect ; calculate intersection of globalRect and device
|
|
move.b (sp)+,d0 ; true if intersection is not empty
|
|
beq nextDevice ; no intersection, go to next device
|
|
|
|
move intersection+right(a6),d0 ; calculate intersection->right - intersection->left
|
|
sub intersection+left(a6),d0
|
|
move intersection+bottom(a6),d1 ; calculate intersection->bottom - intersection->top
|
|
sub intersection+top(a6),d1
|
|
mulu d1,d0 ; calculate area
|
|
|
|
cmp.l d3,d0 ; is area > maximum area up to now?
|
|
ble nextDevice ; no, go to next device
|
|
move.l d0,d3 ; yes, keep new area in d3
|
|
move.l a3,a2 ; remember corresponding device in a2
|
|
|
|
nextDevice
|
|
move.l (a3),a0 ; get pointer to device
|
|
move.l gdNextGD(a0),a3 ; get handle to next device in list
|
|
tst.l a3 ; is there another device?
|
|
bne deviceLoop ; yes, check it out
|
|
|
|
exit move.l a2,maxAreaDevice(a6) ; no, return greatest overlapping device
|
|
|
|
movem.l (sp)+,a2-a4/d3 ; restore regs
|
|
unlk a6 ; get rid of stack frame
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
endif
|
|
|
|
|
|
FindInverseTable PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION FindInverseTable (ctab: CTabHandle): ITabHandle;
|
|
;
|
|
; Find a device that has an inverse table with the same seed as ctab,
|
|
; and return a handle to its inverse table.
|
|
; If the search is unsuccessful, return NIL.
|
|
;
|
|
; NOTE: This algorithm uses the seeds of the color tables and inverse tables
|
|
; for comparison. It is possible to have two identical color tables
|
|
; with the same seed.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
itab equ paramSize+4 ; LONG, ITabHandle result
|
|
ctab equ itab-4 ; LONG, handle to color table
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Get ctab's seed
|
|
|
|
move.l ([ctab,sp]),a0 ; get a pointer to the color table
|
|
move.l ctSeed(a0),d0 ; get the color table's seed
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Go through device list and try to find a device that has an inverse table
|
|
; with a seed identical to the seed of ctab.
|
|
|
|
move.l DeviceList,a0 ; start at beginning of device list
|
|
tst.l a0 ; is there a device (there should, really!)?
|
|
beq.s exit ; exit if no device
|
|
|
|
deviceLoop
|
|
move.l (a0),a0 ; get pointer to device
|
|
move.l gdITable(a0),a2 ; get handle to inverse table
|
|
move.l (a2),a1 ; get pointer to inverse table
|
|
cmp.l ITabSeed(a1),d0 ; are seed identical?
|
|
beq.s exit ; yes, we found it!!
|
|
|
|
move.l gdNextGD(a0),a0 ; get handle to next device in list
|
|
tst.l a0 ; is there another device?
|
|
bne.s deviceLoop ; yes, check it out
|
|
|
|
moveq #nil,a2 ; didn't find anything, return NIL
|
|
|
|
exit move.l a2,itab(sp) ; store handle to inverse table in result
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
GetGWorld PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE GetGWorld (VAR port: CGrafPtr; VAR gdh: GDHandle);
|
|
;
|
|
; Return the current port and gDevice.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 8 ; size of parameters
|
|
port equ paramSize+4-4 ; LONG, address of CGrafPtr variable
|
|
gdh equ port-4 ; LONG, address of GDHandle variable
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
move.l port(sp),a0 ; get address of port variable
|
|
move.l GrafGlobals(a5),a1 ; get address of Quickdraw Globals
|
|
move.l thePort(a1),(a0) ; put the current port in port variable
|
|
|
|
move.l gdh(sp),a0 ; get address of gDevice variable
|
|
move.l theGDevice,(a0) ; store in it current device
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
SetGWorld PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE SetGWorld (port: CGrafPtr; gdh: GDHandle);
|
|
;
|
|
; Set the current port and device.
|
|
;
|
|
; If port is a GWorldPtr, set the current device to its attached device and ignore gdh.
|
|
; If port is not a GWorldPtr, set the current device to gdh.
|
|
;
|
|
; HIDDEN FEATURES:
|
|
; If port is not a GWorldPtr and gdh is NIL, the current device is set to MainDevice.
|
|
; If port is a GWorldPtr but doesn't have an attached device (should never happen),
|
|
; the current device is set to MainDevice.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 8 ; size of parameters
|
|
port equ paramSize+4-4 ; LONG, new current port
|
|
gdh equ port-4 ; LONG, new current device
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Set the current port
|
|
|
|
move.l GrafGlobals(a5),a0 ; get address of Quickdraw Globals
|
|
move.l port(sp),thePort(a0) ; set the current port
|
|
|
|
|
|
move.l gdh(sp),a1 ; get the new device in a1
|
|
|
|
; See if port is a GWorldPtr
|
|
|
|
move.l port(sp),a0 ; get pointer to grafport
|
|
move portVersion(a0),d0 ; get the port's portVersion/rowBytes
|
|
and #GWorldFlag,d0 ; mask all other bits than the GWorldFlag
|
|
cmp #GWorldFlag,d0 ; is it exactly equal to GWorldFlag?
|
|
bne.s setDevice ; if yes, get its attached device
|
|
|
|
; If port is a GWorldPtr, get the attached device in its grafVars substructure
|
|
|
|
move.l ([grafVars,a0]),a0 ; get pointer to the grafVars
|
|
move.l attachDevice(a0),a1 ; get attached device in a1
|
|
|
|
; Set the current device. If gdh is NIL, reset the current device to MainDevice
|
|
|
|
setDevice
|
|
tst.l a1 ; is it NIL?
|
|
bne.s @0 ; yes, reset to MainDevice
|
|
move.l MainDevice,a1 ; get handle to main device
|
|
@0
|
|
move.l a1,theGDevice ; set current device
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
DisposeGWorld PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE DisposeGWorld (offscreenGWorld: GWorldPtr);
|
|
;
|
|
; Dispose all the memory allocated for the offscreen graphics world
|
|
; described by offscreenGWorld.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
offscreenGWorld equ paramSize+4-4 ; LONG, offscreen graphics world
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Check that offscreenGWorld is really a GWorld
|
|
|
|
move.l offscreenGWorld(sp),a0 ; get pointer to grafport
|
|
move portVersion(a0),d0 ; get the port's portVersion/rowBytes
|
|
and #GWorldFlag,d0 ; mask all other bits than the GWorldFlag
|
|
cmp #GWorldFlag,d0 ; is it exactly equal to GWorldFlag?
|
|
bne.s exit ; if no, this isn't a GWorld, don't do anything
|
|
|
|
; Get handle to offscreen buffer
|
|
; If pmVersion=PixMapVers2, baseAddr is a handle
|
|
; If pmVersion=PixMapVers1, baseAddr is the master pointer
|
|
; Otherwise, trouble, don't dispose baseAddr.
|
|
|
|
move.l ([portPixMap,a0]),a1 ; get pointer to pixmap
|
|
move.l baseAddr(a1),a0 ; get pointer/handle to offscreen buffer
|
|
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
cmp #PixMapVers2,d0 ; is pmVersion version 2?
|
|
beq.s @0 ; yes, baseAddr is already a handle
|
|
|
|
cmp #PixMapVers1,d0 ; is pmVersion version 1?
|
|
bne.s dontDisposeBaseAddr ; no, abnormal situation, don't dispose baseAddr
|
|
|
|
; If pmVersion = PixMapVers1, baseAddr is a pointer, recover the handle
|
|
; Note that pmVersion = PixMapVers1 also means the handle is temporarily unpurgeable so
|
|
; the baseAddr is always valid.
|
|
|
|
_RecoverHandle ; get handle to offscreen buffer
|
|
@0
|
|
_DisposHandle ; dispose offscreen buffer
|
|
|
|
; Dispose of the offscreen device if any
|
|
|
|
dontDisposeBaseAddr
|
|
move.l offscreenGWorld(sp),a0 ; get pointer to grafport
|
|
move.l ([grafVars,a0]),a0 ; get pointer to grafVars substructure
|
|
move.b devOwned(a0),d0 ; look at devOwned flag
|
|
beq.s dontDisposeGDevice ; if false, don't deallocate device, we didnt' create it
|
|
|
|
; If the attached device is the current device, reset the current device
|
|
; to MainDevice. We don't want the current device to be garbage, do we?
|
|
|
|
move.l attachDevice(a0),a0 ; get handle to attached device
|
|
cmp.l theGDevice,a0 ; is it the current device?
|
|
bne.s @1 ; no, don't change current device
|
|
move.l MainDevice,theGDevice ; yes, set current device to Main Device
|
|
@1
|
|
move.l a0,-(sp) ; push handle to offscreen device
|
|
_DisposGDevice ; get rid of gDevice structure and substructures
|
|
|
|
|
|
; Dispose of all substructures of the offscreen port
|
|
|
|
dontDisposeGDevice
|
|
move.l offscreenGWorld(sp),-(sp) ; push pointer to offscreen port
|
|
_ClosePort ; get rid of all substructures
|
|
|
|
move.l offscreenGWorld(sp),a0 ; get pointer to grafport
|
|
_RecoverHandle ; find handle to grafport
|
|
_DisposHandle ; dispose memory of grafport structure
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
GetGWorldDevice PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION GetGWorldDevice (offscreenGWorld: GWorldPtr): GDHandle;
|
|
;
|
|
; Returns a handle to the attached device to offscreenGWorld.
|
|
; If offscreenGWorld is not a GWorld, returns the current device.
|
|
;
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
offscreenDevice equ paramSize+4 ; LONG, handle to attached device
|
|
offscreenGWorld equ offscreenDevice-4 ; LONG, offscreen graphics world
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Check that offscreenGWorld is really a GWorld
|
|
|
|
move.l offscreenGWorld(sp),a0 ; get pointer to grafport
|
|
move portVersion(a0),d0 ; get the port's portVersion/rowBytes
|
|
and #GWorldFlag,d0 ; mask all other bits than the GWorldFlag
|
|
cmp #GWorldFlag,d0 ; is it exactly equal to GWorldFlag?
|
|
beq.s getAttachDevice ; if yes, go get the attached device
|
|
|
|
; If offscreenGWorld is not a GWorld, return current device
|
|
|
|
move.l theGDevice,offscreenDevice(sp) ; store the current device in result
|
|
bra.s exit ; and exit
|
|
|
|
; If offscreenGWorld is a GWorld, return the attached device
|
|
|
|
getAttachDevice
|
|
move.l ([grafVars,a0]),a0 ; get pointer to grafVars substructure
|
|
move.l attachDevice(a0),offscreenDevice(sp) ; store handle to attached device in result
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
;Êas seen in QDciPatchROM.a verbatim <sm 6/9/92>stb
|
|
|
|
UpdateGWorld PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; 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
|
|
newNumRowBytes equ horizOffset-2 ; WORD, rowBytes of new offscreen gworld
|
|
reserved equ newNumRowBytes-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 #~(clipPix+stretchPix+ditherPix),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 #clipPix+stretchPix,d0 ; get clipPixBit and stretchPixBit
|
|
cmp.l #clipPix+stretchPix,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 #clipPix+stretchPix,d0 ; is one those bits set?
|
|
beq paramError ; nope, they're both 0, report error and quit
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Remember pointer to offscreen GWorld
|
|
|
|
getOffGWorld
|
|
move.l ([offscreenGWorld,a6]),a3 ; get pointer to offscreen GWorld
|
|
|
|
; Save the current graphics world
|
|
|
|
pea savePort(a6) ; push address of savePort
|
|
pea saveDevice(a6) ; push address of saveDevice
|
|
_GetGWorld ; get current graphics world
|
|
|
|
;----------------------------------------------------------------------------
|
|
; If aGDevice is not NIL, use its depth and color table
|
|
|
|
checkAGDevice
|
|
move.l aGDevice(a6),d0 ; get handle to aGDevice
|
|
beq.s getNewParms ; it's NIL, don't do anything with it
|
|
|
|
move.l d0,a0 ; get handle in a0
|
|
move.l (a0),a0 ; get pointer to aGDevice
|
|
move.l ([gdPMap,a0]),a0 ; get pointer to its pixmap
|
|
move pixelSize(a0),pixelDepth(a6) ; use its pixelSize
|
|
move.l pmTable(a0),cTable(a6) ; and its color table
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Compute new portRect and get new pixSize and color table seed for new offscreen graphics world
|
|
|
|
getNewParms
|
|
move.l boundsRect(a6),a0 ; get pointer to boundsRect
|
|
|
|
; Check range validity of pixelDepth -- it must be between 0 and 32.
|
|
|
|
move pixelDepth(a6),d7 ; pixel resolution
|
|
beq.s useMaxDevice ; if depth = 0, find max resolution
|
|
cmp #32,d7 ; illegal if > 32
|
|
bhi badPixelDepth ; exit with error
|
|
bra.s boundsIsLocal ; no, just copy boundsRect as is
|
|
|
|
;----------------------------------------------------------------------------
|
|
; If pixelDepth = 0:
|
|
; Offset boundsRect in newBounds so that topLeft = (0,0)
|
|
|
|
useMaxDevice
|
|
clr.l newBounds+topLeft(a6)
|
|
move bottom(a0),d0 ; compute newBounds.bottom = boundsRect->bottom - boundsRect->top
|
|
sub top(a0),d0
|
|
move d0,newBounds+bottom(a6)
|
|
move right(a0),d0 ; compute newBounds.right = boundsRect->right - boundsRect->left
|
|
sub left(a0),d0
|
|
move d0,newBounds+right(a6)
|
|
|
|
; Get pixSize from max device
|
|
|
|
clr.l -(sp) ; leave room for GDHandle result
|
|
move.l boundsRect(a6),-(sp) ; pass boundsRect as a global rect in screen space
|
|
_GetMaxDevice ; find deepest device that intersects boundsRect
|
|
move.l (sp)+,d0 ; get handle to max device <KON 6JUN90>
|
|
beq paramError ; if NIL, exit <KON 6JUN90>
|
|
move.l d0,a0 ; <KON 6JUN90>
|
|
move.l a0,maxDevice(a6) ; remember max device
|
|
|
|
move.l (a0),a1 ; get pointer to device
|
|
move.l ([gdPMap,a1]),a0 ; get pointer to its pixmap
|
|
move pixelSize(a0),pixSize(a6) ; get its pixel size
|
|
|
|
; Get color table seed from max device
|
|
|
|
move.l ([pmTable,a0]),a0 ; get pointer to color table
|
|
move.l ctSeed(a0),colTabSeed(a6) ; get its color table seed
|
|
|
|
; Get new pixmap alignment with the max device
|
|
|
|
move.l boundsRect(a6),a0 ; get pointer to boundsRect
|
|
move left(a0),d0 ; get left coordinate of boundsRect
|
|
sub gdRect+left(a1),d0 ; subtract left coordinate of device rectangle
|
|
move d0,horizOffset(a6) ; save offset
|
|
|
|
bra.s checkPixShift
|
|
|
|
;----------------------------------------------------------------------------
|
|
; If pixelDepth is not 0:
|
|
; Copy boundsRect to newBounds without modification
|
|
|
|
boundsIsLocal
|
|
move.l topLeft(a0),newBounds+topLeft(a6) ; copy boundsRect to newBounds
|
|
move.l botRight(a0),newBounds+botRight(a6)
|
|
|
|
; Alignment is 0
|
|
|
|
clr horizOffset(a6) ; no alignment if boundsRect is not global
|
|
|
|
; PixSize = pixelDepth
|
|
|
|
move pixelDepth(a6),pixSize(a6) ; if pixDepth is not 0, pixSize = pixelDepth
|
|
|
|
; If cTable is not 0, get its seed
|
|
|
|
move.l cTable(a6),d0 ; get handle to color table
|
|
beq.s noCTable ; if cTable is 0, use default seed
|
|
|
|
move.l d0,a0 ; get handle to color table
|
|
move.l (a0),a0 ; get pointer to color table
|
|
move.l ctSeed(a0),colTabSeed(a6) ; get color table seed
|
|
bra.s checkPixShift
|
|
|
|
; If cTable is 0, the color table seed is cmpCnt * cmpSize
|
|
|
|
noCtable
|
|
move pixelDepth(a6),d0 ; get pixel depth
|
|
cmp #16,d0 ; is it 16 bits/pixel?
|
|
bne.s check32 ; no, check to see if it is 32 bits/pixel
|
|
|
|
move #3*5,d0 ; if 16 bits/pixel, cmpCnt * cmpSize = 3 * 5
|
|
bra.s setCtSeed
|
|
|
|
check32 cmp #32,d0 ; is it 32 bits/pixel?
|
|
bne.s setCTSeed ; no, then pixelDepth = cmpCnt * cmpSize
|
|
|
|
move #3*8,d0 ; if 32 bits/pixel, cmpCnt * cmpSize = 3 * 8
|
|
|
|
setCtSeed
|
|
ext.l d0 ; convert to long
|
|
move.l d0,colTabSeed(a6) ; remember color table seed
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Convert pixel depth to shift amount
|
|
; Use ShiftTbl for conversion
|
|
|
|
checkPixShift
|
|
move pixSize(a6),d7 ; get pixel size
|
|
lea ShiftTable,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,newNumRowBytes(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,newNumRowBytes(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 #newRowBytes,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 #clipPix,d0 ; is the clipPixBit set?
|
|
bne.s @0 ; yes, use clipping
|
|
move.l #stretchPix,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 #alignPix,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 #newDepth,result(a6) ; different, set scaling bit
|
|
|
|
move.l gDevFlags(a6),d0 ; get flags
|
|
and.l #ditherPix,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 #ditherPix,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 #mapPix,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 #purgePix,newFlags(a6) ; offscreen buffer is purged, it means it's purgeable
|
|
or.l #reallocPix,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 #pixelsPurgeable,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 #purgePix,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 #noNewDevice,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 #useTempMem,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 #reallocPix,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 #mapPix,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 #alignPix,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 newNumRowBytes(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 newNumRowBytes(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 #noNewDevice,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
|
|
jsr 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 #reallocPix,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 #noNewDevice,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 #newRowBytes,result(a6) ; set newRowBytes bit
|
|
@RowBytesFlagDone
|
|
|
|
move.l gDevFlags(a6),d0 ; get the flags
|
|
and.l #clipPix,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
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Until we have Asynchronous Quickdraw, the following code is not included.
|
|
|
|
if AsyncQD then
|
|
|
|
BitMapDone PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION BitMapDone (xm: BitMapPtr): Boolean;
|
|
;
|
|
; Returns true if all pending Quickdraw requests for the given bit/pixmap are completed.
|
|
; Returns false if not.
|
|
;
|
|
; Always returns true in Synchronous Quickdraw.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
result equ paramSize+4 ; BOOLEAN, function result
|
|
xm equ result-4 ; LONG, pointer to bitmap/pixmap
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
move.b #true,result(sp) ; always set result to true
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
|
|
ENDPROC
|
|
|
|
endif
|
|
|
|
|
|
|
|
QDDone PROC EXPORT
|
|
IMPORT BitMapDone
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION QDDone (port: GrafPtr): Boolean;
|
|
;
|
|
; Returns true if all pending Quickdraw requests for the given port are completed.
|
|
; Returns false if not.
|
|
;
|
|
; Call PixMapDone to do the job.
|
|
;
|
|
; This function should be called before accessing the pixels directly (e.g.
|
|
; using distorsion algorithm, etc.) or to make sure that the drawing to a given
|
|
; port is finished (animation, etc.)
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
result equ paramSize+4 ; BOOLEAN, function result
|
|
port equ result-4 ; LONG, pointer to port
|
|
|
|
;----------------------------------------------------------------------------
|
|
; If Asynchronous Quickdraw is present, call BitMapDone
|
|
|
|
if AsyncQD then
|
|
|
|
; Call BitMapDone to do the job
|
|
|
|
move.l port(sp),a0 ; get pointer to port
|
|
_PortToMap ; get pointer to bitmap or pixmap
|
|
|
|
clr.b -(sp) ; leave room for Boolean result
|
|
move.l a0,-(sp) ; push pointer to bit/pixmap
|
|
jsr BitMapDone ; do it
|
|
move.b (sp)+,result(sp) ; store result from BitMapDone in our result
|
|
|
|
; If Asynchronous Quickdraw is not present, just return true
|
|
|
|
else
|
|
|
|
move.b #true,result(sp)
|
|
|
|
endif
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
LockPixels PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION LockPixels (pm: PixMapHandle): Boolean;
|
|
;
|
|
; Lock offscreen buffer down, change the handle in baseAddr to a 32-bit
|
|
; pointer to the offscreen buffer, and change the pmVersion from PixMapVers2 to PixMapVers1.
|
|
;
|
|
; Don't do anything and return false if handle as been purged.
|
|
; Don't do anything and return true if pmVersion is not PixMapVers2.
|
|
;
|
|
; This procedure must be called before drawing to an offscreen world.
|
|
;
|
|
; NOTE: If pmVersion is PixMapVers1, it means LockPixels is being called twice in a row.
|
|
; LockPixels doesn't do anything in this case.
|
|
;
|
|
; The fact that the baseAddr can be locked and unlocked allows Quickdraw
|
|
; to use a relocatable block for offscreen buffers, therefore avoiding heap
|
|
; fragmentation.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
result equ paramSize+4 ; BYTE, result: false if handle is purged
|
|
pm equ result-4 ; LONG, handle to pixmap
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Assume handle isn't purged
|
|
|
|
move.b #true,result(sp) ; set result to true
|
|
|
|
; Check that PixMap's pmVersion is PixMapVers2.
|
|
; If it's not PixMapVers2, don't do anything and return true
|
|
|
|
move.l ([pm,sp]),a1 ; get pointer to pixmap
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
cmp #PixMapVers2,d0 ; is pmVersion version 2?
|
|
bne.s exit ; no, exit
|
|
|
|
; Get 32-bit pointer to offscreen buffer
|
|
|
|
move.l baseAddr(a1),a0 ; get handle to offscreen buffer
|
|
move.l (a0),d0 ; get master pointer
|
|
if UseTranslate24To32 then
|
|
_rTranslate24To32 ; translate to 32-bit valid pointer
|
|
else
|
|
_StripAddress ; if 32-bit QD not present, don't use Translate24To32
|
|
endif
|
|
|
|
; Check that the offscreen buffer isn't purged
|
|
|
|
tst.l d0 ; is pointer to offscreen buffer = 0?
|
|
bne.s @0 ; no, continue as planned
|
|
move.b #false,result(sp) ; yes, it's purged, return false
|
|
bra.s exit ; and exit
|
|
@0
|
|
|
|
; Store 32-bit pointer in baseAddr
|
|
|
|
move.l d0,baseAddr(a1) ; baseAddr can now be used by 32-bit Quickdraw correctly
|
|
|
|
; Change pmVersion to reflect that baseAddr is a 32-bit pointer
|
|
|
|
move #PixMapVers1,pmVersion(a1) ; set pmVersion to PixMapVers1 (baseAddr is 32-bit pointer)
|
|
|
|
; Lock down handle to offscreen buffer
|
|
|
|
_HLock ; lock it (a0 contains the handle)
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
UnlockPixels PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE UnlockPixels (pm: PixMapHandle);
|
|
;
|
|
; If pmVersion is PixMapVers1, change the baseAddr from a pointer to a handle, unlock
|
|
; the handle, and change pmVersion to PixMapVers2.
|
|
;
|
|
; If pmVersion is not 1, don't do anything.
|
|
;
|
|
; NOTE: If pmVersion is PixMapVers2, UnlockPixels is being called twice.
|
|
; UnlockPixels doesn't do anything in this case.
|
|
;
|
|
; This procedure must be called when the application is finished drawing
|
|
; to the offscreen pixmap.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
pm equ paramSize+4-4 ; LONG, handle to pixmap
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Check that PixMap's pmVersion is PixMapVers1. If it's not PixMapVers1, don't do anything
|
|
|
|
move.l ([pm,sp]),a1 ; get pointer to pixmap
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
cmp #PixMapVers1,d0 ; is pmVersion version 1?
|
|
bne.s exit ; no, exit
|
|
|
|
; If pmVersion = PixMapVers1, convert the baseAddr to a handle and unlock it
|
|
|
|
move.l baseAddr(a1),a0 ; push address of offscreen buffer
|
|
_RecoverHandle ; get handle to offscreen buffer
|
|
_HUnlock ; unlock it
|
|
|
|
; Store handle in baseAddr
|
|
|
|
move.l ([pm,sp]),a1 ; get pointer to pixmap
|
|
move.l a0,baseAddr(a1) ; store handle to offscreen buffer in baseAddr
|
|
|
|
; Change pmVersion to PixMapVers2 to reflect that baseAddr is a handle
|
|
|
|
move #PixMapVers2,pmVersion(a1) ; set pmVersion to version 2 (baseAddr is a handle)
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
PortChanged PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE PortChanged (port: CGrafPtr);
|
|
;
|
|
; Called after non-procedural changes are made to a port.
|
|
; This procedure should be called before doing any more drawing.
|
|
;
|
|
; Note: this procedure is useful for Asynchronous Quickdraw
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
port equ paramSize+4-4 ; LONG, pointer to GrafPort
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; doesn't do anything in Synchronous Quickdraw
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
PixPatChanged PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE PixPatChanged (ppat: PixPatHandle);
|
|
;
|
|
; Called after non-procedural changes are made to a pixel pattern.
|
|
; This procedure should be called before doing any more drawing.
|
|
;
|
|
; Note: this procedure is useful for Asynchronous Quickdraw
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
ppat equ paramSize+4-4 ; LONG, handle to pixpat
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Flag pattern's expanded data as invalid
|
|
|
|
move.l ppat(sp),a0 ; get handle to pixpat
|
|
move.l (a0),a0 ; get pointer to pixpat
|
|
move #-1,patXValid(a0) ; mark pattern's expanded data as invalid
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
CTabChanged PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE CTabChanged (cTab: CTabHandle);
|
|
;
|
|
; Called after non-procedural changes are made to a color table.
|
|
; This procedure should be called before doing any more drawing.
|
|
;
|
|
; Note: this procedure is useful for Asynchronous Quickdraw
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
cTab equ paramSize+4-4 ; LONG, handle to color table
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Get a new seed for the color table
|
|
|
|
clr.l -(sp) ; leave room for longint result
|
|
_GetCTSeed ; get a new seed
|
|
move.l (sp)+,d0 ; get the seed
|
|
|
|
move.l ([cTab,sp]),a0 ; get pointer to color table
|
|
move.l d0,ctSeed(a0) ; store new seed in color table
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
GDeviceChanged PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE GDeviceChanged (gdh: GDHandle);
|
|
;
|
|
; Called after non-procedural changes are made to a gDevice
|
|
; This procedure should be called before doing any more drawing.
|
|
;
|
|
; Note: this procedure is useful for Asynchronous Quickdraw
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
gdh equ paramSize+4-4 ; LONG, handle to gDevice
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; doesn't do anything in Synchronous Quickdraw
|
|
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
AllowPurgePixels PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE AllowPurgePixels (pm: PixMapHandle);
|
|
;
|
|
; Allow purging of the offscreen buffer by calling HPurge.
|
|
;
|
|
; If pmVersion is PixMapVers2, baseAddr is a handle, call HPurge directly.
|
|
; If pmVersion is PixMapVers1, baseAddr is a pointer, get the handle first.
|
|
; If pmVersion is not PixMapVers1 or PixMapVers2, don't do anything.
|
|
;
|
|
; NOTE: It is safe to set the purge state of the handle to the offscreen
|
|
; buffer even if the baseAddr contains only the pointer. The reason
|
|
; is that if the baseAddr is a pointer, it means LockPixels has been
|
|
; called and therefore the handle is locked and won't be purged.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
pm equ paramSize+4-4 ; LONG, handle to pixmap
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Check PixMap's pmVersion.
|
|
|
|
move.l ([pm,sp]),a1 ; get pointer to pixmap
|
|
move.l baseAddr(a1),a0 ; get baseAddr
|
|
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
cmp #PixMapVers2,d0 ; is pmVersion version 2?
|
|
beq.s setPurge ; yes, we're ok
|
|
cmp #PixMapVers1,d0 ; is pmVersion version 1?
|
|
bne.s exit ; no, don't do anything
|
|
|
|
; If pmVersion is PixMapVers1, get the handle to the offscreen buffer
|
|
|
|
_RecoverHandle ; get handle to offscreen buffer
|
|
|
|
; Make offscreen buffer purgeable
|
|
|
|
setPurge
|
|
_HPurge ; make it purgeable
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
NoPurgePixels PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE NoPurgePixels (pm: PixMapHandle);
|
|
;
|
|
; Prevents purging of the offscreen buffer by calling HNoPurge.
|
|
;
|
|
; If pmVersion is PixMapVers2, baseAddr is a handle, call HNoPurge directly.
|
|
; If pmVersion is PixMapVers1, baseAddr is a pointer, recover the handle first.
|
|
; If pmVersion is not PixMapVers1 or PixMapVers2, don't do anything.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
pm equ paramSize+4-4 ; LONG, handle to pixmap
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Check PixMap's pmVersion.
|
|
|
|
move.l ([pm,sp]),a1 ; get pointer to pixmap
|
|
move.l baseAddr(a1),a0 ; get baseAddr
|
|
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
cmp #PixMapVers2,d0 ; is pmVersion version 2?
|
|
beq.s setNoPurge ; yes, we're ok
|
|
cmp #PixMapVers1,d0 ; is pmVersion version 1?
|
|
bne.s exit ; no, don't do anything
|
|
|
|
; If pmVersion is PixMapVers1, baseAddr is a pointer, get handle to offscreen buffer
|
|
|
|
_RecoverHandle ; get handle to offscreen buffer
|
|
|
|
; Make offscreen buffer unpurgeable
|
|
|
|
setNoPurge
|
|
_HNoPurge ; make it unpurgeable
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
GetPixelsState PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION GetPixelsState (pm: PixMapHandle): LONGINT;
|
|
;
|
|
; Get the state of the offscreen buffer handle by calling HGetState. The result
|
|
; contains two bits: pixelsLockedBit and pixelsPurgeableBit.
|
|
; For convenience, these bits happen to be the same as the lock and purge bit
|
|
; of the Memory Manager.
|
|
;
|
|
; If pmVersion is PixMapVers2, the baseAddr is a handle, call HGetState directly.
|
|
; If pmVersion is PixMapVers1, the baseAddr is a pointer, call RecoverHandle first.
|
|
; If pmVersion is neither, return 0.
|
|
;
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
state equ paramSize+4 ; LONG, result
|
|
pm equ state-4 ; LONG, handle to pixmap
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Start with a state of 0
|
|
|
|
clr.l state(sp)
|
|
|
|
; Check PixMap's pmVersion.
|
|
|
|
move.l ([pm,sp]),a1 ; get pointer to pixmap
|
|
move.l baseAddr(a1),a0 ; get baseAddr
|
|
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
cmp #PixMapVers2,d0 ; is pmVersion version 2?
|
|
beq.s @0 ; yes, baseAddr is a handle
|
|
|
|
cmp #PixMapVers1,d0 ; is pmVersion version 1?
|
|
bne.s exit ; no, don't do anything
|
|
|
|
; If pmVersion = 1, get the handle to the offscreen buffer
|
|
|
|
_RecoverHandle ; get the handle in a0
|
|
@0
|
|
_HGetState ; get the state in low byte of d0
|
|
|
|
move.l d0,state(sp) ; store state in result
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
SetPixelsState PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE SetPixelsState (pm: PixMapHandle; flags: LONGINT);
|
|
;
|
|
; Set the state of the offscreen buffer handle by calling LockPixels/UnlockPixels
|
|
; and AllowPurgePixels/NoPurgePixels.
|
|
;
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 8 ; size of parameters
|
|
pm equ paramSize+4-4 ; LONG, handle to pixmap
|
|
pixMapFlags equ pm-4 ; LONG, flags
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Check pixelsPurgeableBit and call AllowPurgePixels or NoPurgePixels
|
|
|
|
move.l pixMapFlags(sp),d0 ; get the flags
|
|
btst.l #pixelsPurgeableBit,d0 ; is pixelsPurgeableBit set?
|
|
bne.s allowPurge ; yes, call AllowPurgePixels
|
|
|
|
move.l pm(sp),-(sp) ; no, call NoPurgePixels
|
|
_NoPurgePixels
|
|
bra checkLock
|
|
|
|
allowPurge
|
|
move.l pm(sp),-(sp) ; call AllowPurgePixels
|
|
_AllowPurgePixels
|
|
|
|
; Check pixelsLockedBit and call LockPixels or UnlockPixels
|
|
|
|
checkLock
|
|
move.l pixMapFlags(sp),d0 ; get the flags
|
|
btst.l #pixelsLockedBit,d0 ; is pixelsLockedBit set?
|
|
bne.s lockIt ; yes, call LockPixels
|
|
|
|
move.l pm(sp),-(sp) ; no, call UnlockPixels
|
|
_UnlockPixels
|
|
bra.s exit
|
|
|
|
lockIt
|
|
move.l pm(sp),a0 ; get PixMapHandle
|
|
clr.b -(sp) ; room for Boolean result
|
|
move.l a0,-(sp) ; push PixMapHandle
|
|
_LockPixels ; call LockPixels
|
|
move.b (sp)+,d0 ; ignore result
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
GetPixBaseAddr PROC EXPORT
|
|
IMPORT BitMapDone
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION GetPixBaseAddr (pm: PixMapHandle): Ptr;
|
|
;
|
|
; Make sure that Asynchronous Quickdraw is done and get the 32-bit pointer to
|
|
; the offscreen buffer.
|
|
;
|
|
; If pmVersion is PixMapVers4, the baseAddr is a 32-bit pointer, just return it. <06Jul89> BAL
|
|
; If pmVersion is PixMapVers2, the baseAddr is a handle, get the 24-bit pointer and clean it.
|
|
; If pmVersion is PixMapVers1, the baseAddr is a clean 24-bit pointer, just return it.
|
|
; If pmVersion is PixMapVers0, <06Jul89> BAL
|
|
; if the baseAddr is the same as one of the screens in the devicelist then return it <06Jul89> BAL
|
|
; else clean it first. <06Jul89> BAL
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
bufResult equ paramSize+4 ; LONG, result
|
|
pm equ bufResult-4 ; LONG, handle to pixmap
|
|
|
|
;----------------------------------------------------------------------------
|
|
; If Asynchronous Quickdraw is present, make sure that it has completed all
|
|
; requests to this pixmap
|
|
|
|
if AsyncQD then
|
|
|
|
WaitBitMapDone
|
|
move.l ([pm,sp]),a0 ; get pointer to pixmap
|
|
clr.b -(sp) ; leave room for boolean result
|
|
move.l a0,-(sp) ; push pointer to pixmap
|
|
jsr BitMapDone ; is drawing to pixmap completed yet?
|
|
move.b (sp)+,d0 ; get result
|
|
beq.s WaitBitMapDone ; no, wait until it's done
|
|
|
|
endif
|
|
|
|
; Initialize bufPtr to baseAddr (assume pmVersion is not PixMapVers2).
|
|
|
|
move.l ([pm,sp]),a1 ; get pointer to pixmap
|
|
move.l baseAddr(a1),a0 ; get baseAddr
|
|
move.l a0,bufResult(sp) ; store in result
|
|
|
|
; Check PixMap's pmVersion.
|
|
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
beq.s chkForScreen ; go check to see if it's a screen <06Jul89> BAL
|
|
btst #PixMapVers2Bit,d0 ; is it a handle?
|
|
beq.s exit ; no, we're done
|
|
|
|
; If pmVersion = PixMapVers2, baseAddr is a handle, get the master pointer
|
|
; and translate it to a 32-bit pointer.
|
|
|
|
move.l (a0),d0 ; get master pointer
|
|
StripBase
|
|
if UseTranslate24To32 then
|
|
_rTranslate24To32 ; translate to 32-bit valid pointer
|
|
else
|
|
_StripAddress ; if 32-bit QD not present, don't use Translate24To32
|
|
endif
|
|
move.l d0,bufResult(sp) ; store it in result
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
chkForScreen
|
|
move.l a0,d0 ; save baseAddr in d0 <06Jul89> BAL
|
|
MOVE.L DEVICELIST,A1 ; GET FIRST ELEMENT IN DEVICE LIST <06Jul89> BAL
|
|
NEXTGD MOVE.L (A1),A0 ; POINT TO DEVICE <06Jul89> BAL
|
|
MOVE.L GDPMAP(A0),A0 ; GET PIXMAP <06Jul89> BAL
|
|
MOVE.L (A0),A0 ; POINT TO PIXMAP <06Jul89> BAL
|
|
cmp.l baseAddr(A0),D0 ; GET PIXEL DEPTH <06Jul89> BAL
|
|
beq.s exit ; same as a screen so don't strip! <06Jul89> BAL
|
|
MOVE.L (A1),A0 ; GET DEVICE <06Jul89> BAL
|
|
MOVE.L GDNEXTGD(A0),D1 ; GET NEXT DEVICE <06Jul89> BAL
|
|
MOVE.L D1,A1 ; SAVE IT <06Jul89> BAL
|
|
BNE.S NEXTGD ; <06Jul89> BAL
|
|
bra.s StripBase ; not a screen so strip the address <06Jul89> BAL
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
; as in QDciPatchROM.a <sm 6/9/92>stb
|
|
|
|
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
|
|
|
|
|
|
; as seen in QDciPatchROM.a <sm 6/9/92>stb
|
|
|
|
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
|
|
|
|
|
|
|
|
NewScreenBuffer PROC EXPORT
|
|
IMPORT FindInverseTable, ShiftTable
|
|
EXPORT NewTempScreenBuffer
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; FUNCTION NewScreenBuffer (globalRect: Rect; purgeable: BOOLEAN; <14Jul89> JCM
|
|
; VAR gdh: GDHandle; VAR offscreenPixMap: PixMapHandle): QDErr;
|
|
;
|
|
; Creates an offscreen pixmap and an offscreen buffer, using globalRect as a global
|
|
; rectangle in screen space and finding the deepest device that intersects that
|
|
; rectangle. The device is returned in gdh, the offscreen PixMap is created
|
|
; according to the characteristics of the device (pixel depth, color table, etc.).
|
|
; The color table is shared with the device.
|
|
|
|
move.b #0,d0 ; MF temp mem selector = 0 (don't use MF temp mem) <14Jul89> JCM
|
|
bra.s CommonScreenBuffer ; branch to common code <14Jul89> JCM
|
|
|
|
;---------------------------------------------------------------------------- <14Jul89> JCM
|
|
; <14Jul89> JCM
|
|
; FUNCTION NewTempScreenBuffer (globalRect: Rect; purgeable: BOOLEAN; <14Jul89> JCM
|
|
; VAR gdh: GDHandle; VAR offscreenPixMap: PixMapHandle): QDErr; <14Jul89> JCM
|
|
; <14Jul89> JCM
|
|
; Same as NewScreenBuffer but allocates the pixels in MultiFinder temporary memory <14Jul89> JCM
|
|
|
|
NewTempScreenBuffer ; <14Jul89> JCM
|
|
move.b #1,d0 ; MF temp mem selector = 1 (use MF temp mem) <14Jul89> JCM
|
|
|
|
|
|
CommonScreenBuffer ; <14Jul89> JCM
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; A6 offsets of parameters after link:
|
|
;
|
|
paramSize equ 14 ; size of parameters
|
|
result equ paramSize+8 ; WORD, QDErr
|
|
boundsRect equ result-4 ; LONG, address of global Rectangle
|
|
purgeable equ boundsRect-2 ; BOOLEAN, purgeable pixels flag <14Jul89> JCM
|
|
gdhP equ purgeable-4 ; LONG, address of GDHandle variable <14Jul89> JCM
|
|
offscreenPMP equ gdhP-4 ; LONG, address of PixMapHandle variable
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; A6 offsets of local variables after link:
|
|
;
|
|
|
|
pixelShift equ -2 ; WORD, pixel shift amount
|
|
bytesPerRow equ pixelShift-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
|
|
museDevice equ offscreenPixMap-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)
|
|
MFTempFlag equ localRect-2 ; BOOLEAN, flag set if using MultiFinder mem for the pixels <14Jul89> JCM
|
|
varSize equ MFTempFlag ; size of local variables <14Jul89> JCM
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
link a6,#varSize ; allocate local variables
|
|
movem.l d3-d7/a2-a4,-(sp) ; save regs
|
|
|
|
move.b d0,MFTempFlag(a6) ; remember state of MFTempFlag <14Jul89> JCM
|
|
|
|
;-------------------------------------------------------------------------
|
|
; 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
|
|
|
|
;-------------------------------------------------------------------------
|
|
; 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
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Use boundsRect as a rectangle in global screen space
|
|
; to find deepest device that intersects that rectangle.
|
|
|
|
findMaxDevice
|
|
clr.l -(sp) ; leave room for GDHandle result
|
|
move.l boundsRect(a6),-(sp) ; pass boundsRect as a global rectangle in screen space
|
|
_GetMaxDevice ; find deepest device that intersects boundsRect
|
|
move.l (sp)+,d0 ; get handle to max device <KON 6JUN90>
|
|
beq paramError ; if NIL, exit <KON 6JUN90>
|
|
move.l d0,a0 ; <KON 6JUN90>
|
|
move.l a0,museDevice(a6) ; use this device as our new source of inspiration
|
|
|
|
;-------------------------------------------------------------------------
|
|
; For maximum efficiency when copying offscreen pixmap to screen, try
|
|
; to match the pixel alignment of the offscreen pixmap to the pixel
|
|
; alignment of the portion of screen space described by boundsRect.
|
|
|
|
computeAlignment
|
|
|
|
; First step: compute horizontal offset between boundsRect and muse device
|
|
|
|
move.l (a0),a0 ; get pointer to device
|
|
move.l boundsRect(a6),a1 ; get pointer to boundsRect
|
|
move left(a1),d0 ; get left coordinate of boundsRect
|
|
sub gdRect+left(a0),d0 ; subtract left coordinate of device rectangle
|
|
move d0,horizOffset(a6) ; save offset
|
|
|
|
; Second step: convert boundsRect to local coordinates (topLeft = 0, 0)
|
|
|
|
move right(a1),d0 ; compute boundsRect->right - boundsRect->left
|
|
sub left(a1),d0
|
|
move d0,localRect+right(a6) ; store in localRect.right
|
|
move bottom(a1),d0 ; compute boundsRect->bottom - boundsRect->top
|
|
sub top(a1),d0
|
|
move d0,localRect+bottom(a6) ; store in localRect.bottom
|
|
clr.l localRect+topLeft(a6) ; set localRect.top and localRect.left to 0
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If pixelDepth = 0, we get the pixel resolution from the museDevice
|
|
|
|
move.l ([museDevice,a6]),a0 ; get pointer to museDevice
|
|
move.l ([gdPMap,a0]),a1 ; get pointer to its pixmap
|
|
move pmPixelSize(a1),d7 ; d7 = pixel resolution to use
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Convert pixel depth to shift amount.
|
|
; pixelShift = log2(pixelDepth). If pixelShift is not integer, pixelShift is invalid.
|
|
; Use a conversion table that is valid for integers from 0 to 32
|
|
; Table returns 0,1,2,3,4 or -1 if pixelDepth is not a power of 2.
|
|
|
|
checkPixelShift
|
|
lea ShiftTable,a0 ; table to convert pixelDepth to pixelShift (exponent of 2)
|
|
moveq #0,d0 ; clear high byte
|
|
move.b 0(a0,d7),d0 ; fetch table
|
|
bmi badPixelDepth ; if table returned -1, pixelDepth is invalid, exit w/error
|
|
|
|
move d0,pixelShift(a6) ; save exponent in pixelShift
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Calculate pixmap bounds.
|
|
; Take into account the horizontal offset. The horizontal offset represents
|
|
; the number of unused pixels at the beginning at each line of the offscreen
|
|
; pixmap, so that the offscreen pixmap is aligned to the screen.
|
|
; The horizontal offset has a meaning only when pixelDepth = 0.
|
|
|
|
move.w localRect+top(a6),pixmapBounds+top(a6) ; pixmapBounds.top = localRect.top
|
|
|
|
; Convert horizOffset to a number of bits modulo 32 and
|
|
; offset pixmapBounds.left with the equivalent number of pixels.
|
|
|
|
move.w horizOffset(a6),d1 ; get horizontal offset in pixels
|
|
lsl.w d0,d1 ; convert to bits
|
|
and.w #$1F,d1 ; offset modulo 32
|
|
lsr.w d0,d1 ; convert back to pixels
|
|
|
|
move.w localRect+left(a6),d0 ; pixmapBounds.left = localRect.left - pixelOffset
|
|
sub.w d1,d0
|
|
move.w d0,pixmapBounds+left(a6) ; store in pixmapBounds
|
|
|
|
move.l localRect+botRight(a6),pixmapBounds+botRight(a6) ; pixmapBounds.botRight = localRect.botRight <11>
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Allocate the actual offscreen buffer.
|
|
; rowBytes is computed as the smallest number of longs containing one line of pixels,
|
|
; converted to bytes:
|
|
; (((pixmapBounds.right - pixmapBounds.left) * pixelSize + 31) / 32) * 4
|
|
;
|
|
; NOTE: pixmapBounds is used here because the buffer is never realigned for a different <12>
|
|
; alignment; thus the current length is exactly correct. <12>
|
|
;
|
|
; size of the buffer is:
|
|
; rowBytes * (pixmapBounds.bottom - pixmapBounds.top)
|
|
|
|
allocateBuffer
|
|
move pixmapBounds+right(a6),d0 ; get right coordinate <12>
|
|
sub pixmapBounds+left(a6),d0 ; compute number of pixels per line <12>
|
|
ext.l d0 ; convert to long
|
|
move pixelShift(a6),d1 ; get shift amount for this pixel resolution
|
|
lsl.l d1,d0 ; convert pixels to bits
|
|
add.l #31,d0 ; add 31 bits
|
|
lsr.l #5,d0 ; convert bits to longs
|
|
lsl.w #2,d0 ; convert longs to bytes
|
|
move d0,bytesPerRow(a6) ; save # of bytes in a row
|
|
|
|
move pixmapBounds+bottom(a6),d1 ; compute height of rectangle <12>
|
|
sub pixmapBounds+top(a6),d1 ; bottom-top <12>
|
|
mulu.w d1,d0 ; compute height * rowBytes
|
|
|
|
tst.b MFTempFlag(a6) ; use MF temp memory? <14Jul89> 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 #cTempMemErr,d0 ; yes, report error <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 a0,offscreenBufH(a6) ; save handle to offscreen buffer
|
|
|
|
_MoveHHi ; move the buffer as high as possible in memory
|
|
|
|
; If the purgeable flag is set, make the offscreen buffer purgeable <14Jul89> JCM
|
|
|
|
tst.b purgeable(a6) ; is purgeable flag set? <14Jul89> JCM
|
|
beq.s @0 ; no, leave as is
|
|
_HPurge ; yes, make it purgeable
|
|
@0
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Create the offscreen PixMap.
|
|
; The baseAddr is a handle to the offscreen buffer.
|
|
; IMPORTANT: the pmVersion field is set to PixMapVers2.
|
|
; pmVersion = PixMapVers2 means that the baseAddr is a handle.
|
|
; pmVersion = PixMapVers1 means that the baseAddr is a 32-bit pointer.
|
|
|
|
createPixMap
|
|
moveq #pmRec,d0 ; get size of PixMap structure
|
|
_NewHandle ,CLEAR ; allocate the handle
|
|
bne reportError ; if Memory Manager error, report it and quit
|
|
|
|
move.l a0,offscreenPixMap(a6) ; save it
|
|
move.l (a0),a1 ; a1 = pixmap pointer
|
|
|
|
; Start filling out the fields of the pixmap
|
|
|
|
move.l offscreenBufH(a6),pmBaseAddr(a1) ; store HANDLE to offscreen buffer in pixmap
|
|
move bytesPerRow(a6),d0 ; get # of bytes in a row
|
|
or #pmFlag,d0 ; flag pixmap as being a Color Quickdraw pixmap
|
|
move d0,pmRowBytes(a1) ; store rowBytes and pixmap flag in pixmap
|
|
move.l pixmapBounds+topLeft(a6),pmBounds+topLeft(a1) ; copy pixmapBounds to pixmap's bounds
|
|
move.l pixmapBounds+botRight(a6),pmBounds+botRight(a1)
|
|
move #PixMapVers2,pmVersion(a1) ; IMPORTANT: set pixmap's version to version 2 (baseAddr is a handle)
|
|
move #72,pmHRes(a1) ; hRes = 72.0 in fixed format
|
|
move #72,pmVRes(a1) ; vRes = 72.0 in fixed format
|
|
|
|
move d7,pmPixelSize(a1) ; store d7 (pixelDepth) in pixmap
|
|
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Note: Some fields will not be initialized. They remain set to 0. Those
|
|
; fields are: packType, packSize, planeBytes, pmReserved.
|
|
|
|
;-------------------------------------------------------------------------
|
|
; The remaining fields of the pixmap are determined differently whether
|
|
; the pixel depth is 1,2,4,8 or 16,32.
|
|
|
|
cmp #16,d7 ; if pixel depth < 16,
|
|
blt.s clutPixels ; do things the classic way
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If the pixel depth is 16 or 32, pixel characteristics are:
|
|
;
|
|
; pixel type = RGB chunky direct (16)
|
|
; pixel size = 16 or 32
|
|
; component count = 3 (R,G,B)
|
|
; component size = 5 or 8
|
|
|
|
move #16,pmPixelType(a1) ; pixelType = RGB chunky direct
|
|
move #3,pmCmpCount(a1) ; cmpCount = 3
|
|
moveq #8,d0 ; assume component size = 8 (32 bits/pixel)
|
|
cmp #32,d7 ; depth = 32 bits/pixel?
|
|
beq.s @0 ; yes, cmpSize = 8
|
|
moveq #5,d0 ; no, cmpSize = 5
|
|
@0 move d0,pmCmpSize(a1) ; store cmpSize in pixmap
|
|
|
|
bra.s getColorTable ; go get the dummy color table from museDevice
|
|
|
|
;-------------------------------------------------------------------------
|
|
; If the pixel depth is 1,2,4,or 8, pixel characteristics are:
|
|
;
|
|
; pixel type = chunky (0)
|
|
; pixel size = 1,2,4,or 8
|
|
; component count = 1
|
|
; component size = pixel size
|
|
|
|
clutPixels
|
|
move #0,pmPixelType(a1) ; pixelType = chunky
|
|
move #1,pmCmpCount(a1) ; 1 component (the pixel index)
|
|
move d7,pmCmpSize(a1) ; cmpSize = pixelSize
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Share the color table with the museDevice
|
|
|
|
getColorTable
|
|
move.l ([museDevice,a6]),a0 ; get pointer to the museDevice
|
|
move.l ([gdPMap,a0]),a0 ; get pointer to its pixmap
|
|
move.l pmTable(a0),pmTable(a1) ; copy the handle to its color table in offscreen PixMap
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Store the offscreen PixMap and museDevice in the offscreenPixMap and gdh VARs
|
|
|
|
move.l offscreenPMP(a6),a0 ; get address of PixMapHandle variable
|
|
move.l offscreenPixMap(a6),(a0) ; store handle to offscreen PixMap in it
|
|
move.l gdhP(a6),a0 ; get address of GDHandle variable
|
|
move.l museDevice(a6),(a0) ; store handle to museDevice in it
|
|
|
|
;-------------------------------------------------------------------------
|
|
; We're done. Return error code and put a copy of it in low-memory QDErr.
|
|
|
|
goHome move result(a6),d0 ; get error code in to d0 for return <29May89> BAL
|
|
ext.l d0 ; make it a long <29May89> BAL
|
|
move d0,QDErr ; copy error code to low-memory global QDErr <29May89> BAL
|
|
movem.l (sp)+,d3-d7/a2-a4 ; restore regs
|
|
unlk a6 ; get rid of stack frame
|
|
rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
;-------------------------------------------------------------------------
|
|
; When an error occurs, all allocated memory is freed and an error code
|
|
; is returned.
|
|
|
|
badPixelDepth
|
|
move #cDepthErr,result(a6) ; pixel depth invalid
|
|
bra.s disposOffscreenHandles ; release memory and exit
|
|
|
|
paramError
|
|
move #paramErr,result(a6) ; one of the parameters is invalid
|
|
bra.s disposOffscreenHandles ; release memory and exit
|
|
|
|
reportError
|
|
move d0,result(a6) ; directly report Memory Manager error
|
|
bra.s disposOffscreenHandles ; release memory and exit
|
|
|
|
makeITabError
|
|
move QDErr,result(a6) ; return QD error
|
|
; bra.s disposOffscreenHandles ; release memory and exit
|
|
|
|
; Dispose of all allocated memory (handle is allocated when non zero)
|
|
|
|
disposOffscreenHandles
|
|
|
|
move.l offscreenBufH(a6),a0 ; get handle to offscreen buffer <11>
|
|
_DisposHandle ; dispose it
|
|
move.l offscreenPixMap(a6),a0 ; get handle to offscreen pixmap <11>
|
|
_DisposHandle ; dispose it
|
|
bra.s goHome ; exit
|
|
|
|
|
|
|
|
|
|
DisposeScreenBuffer PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE DisposeScreenBuffer (offscreenPixMap: PixMapHandle);
|
|
;
|
|
; Dispose the memory allocated for the offscreen pixmap and offscreen buffer.
|
|
; I don't use DisposPixMap because the color table is owned by the device,
|
|
; not the pixmap.
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Stack offsets of parameters
|
|
;
|
|
paramSize equ 4 ; size of parameters
|
|
offscreenPixMap equ paramSize+4-4 ; LONG, handle to offscreen PixMap
|
|
|
|
;----------------------------------------------------------------------------
|
|
|
|
; Check offscreenPixMap's pmVersion. If not PixMapVers1 or PixMapVers2, don't do anything.
|
|
; Get handle to offscreen buffer
|
|
; If pmVersion=PixMapVers2, baseAddr is a handle
|
|
; If pmVersion=PixMapVers1, baseAddr is the master pointer
|
|
|
|
move.l ([offscreenPixMap,sp]),a1 ; get pointer to offscreen PixMap
|
|
move.l baseAddr(a1),a0 ; get pointer/handle to offscreen buffer
|
|
|
|
move pmVersion(a1),d0 ; get pmVersion
|
|
cmp #PixMapVers2,d0 ; is pmVersion version 2?
|
|
beq.s @0 ; yes, baseAddr is a handle
|
|
|
|
cmp #PixMapVers1,d0 ; is pmVersion version 1?
|
|
bne.s exit ; no, this pixmap wasn't created by me, exit
|
|
|
|
; If pmVersion = PixMapVers1, baseAddr is a pointer, recover the handle
|
|
; Note that pmVersion = PixMapVers1 also means the handle is temporarily unpurgeable so
|
|
; the baseAddr is always valid.
|
|
|
|
_RecoverHandle ; get handle to offscreen buffer
|
|
@0
|
|
_DisposHandle ; dispose offscreen buffer
|
|
|
|
; Dispose of the offscreen pixmap structure
|
|
|
|
move.l offscreenPixMap(sp),a0 ; get handle to offscreen PixMap
|
|
_DisposHandle ; get rid of it
|
|
|
|
exit rtd #paramSize ; get rid of parameters and return to caller
|
|
|
|
ENDPROC
|
|
|
|
|
|
; as in QDciPatchROM.a <sm 6/9/92>stb
|
|
|
|
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.
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; 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
|
|
|
|
|
|
|
|
QDExtEnd PROC EXPORT
|
|
;----------------------------------------------------------------------------
|
|
; This is the end of the code for Quickdraw Extensions
|
|
|
|
ENDPROC
|