sys7.1-doc-wip/QuickDraw/PaletteMgr.a

6081 lines
230 KiB
Plaintext
Raw Permalink Normal View History

2020-05-10 05:37:38 +00:00
;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Elliot make this change
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
2019-07-27 14:37:48 +00:00
;__________________________________________________________________________________________________
; File: PaletteMgr.a
;
; Contains: The Palette Manager
;
; Written by: Art Cabral and David Van Brink and lots of others
;
; Copyright: © 1987-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM10> 10-19-93 jmp Removed the ctSeed whacking (Kon explained the error of my
; ways). Well have to come up with some other method to fix
; dimming.
; <SM7> 08-03-93 jmp Changed the SetDepth code so that the MenuBar gets redrawn first
; after a depth switch. This is the way the pre-System7 Monitors
; 'cdev' did things. And it looks much nicer.
; <SM6> 1/13/93 kc Export ReleaseList so that we can vectorize it.
; <SM5> 12/11/92 HI Changes the HasLayers conditional to 1 from 0. SuperMario ROM
; has LayerMgr. Wrong conditional produced the wrong code in
; SetDepth which ends up calling PaintOne/PaintBehind sequence
; instead of RedrawAll. This fixes the problem of balloon help
; update problem when changing bit depths within Monitors CP.
; (Hoon Im)
; <SM4> 5/21/92 kc Change the name of Allocate to PMAllocate to avoid name conflict
; with the glue.
; <SM3> 5/4/92 FM fix typo
; <SM2> 5/4/92 FM Roll in changes from PatchIICiRom.a file that were "lost" in the
; review process…Save and restore window list in PMgrExit. Also
; zero out d3/d4 in resize palette so that the high word won
; <45> 7/10/91 JSM Remove obsolete SysVers conditional and obsolete ExitToShell
; patch.
;
; <44> 2/26/91 DFH csd,WS#910226a: Fixed bug in ptchPMgrExit where it assumed that
; graphics has been initialized. Bug introduced by change <43>.
; <43> 1/18/91 dvb Don't restore color environment if it hasn't been changed.
; <42> 1/3/91 VL (ngk) Replaced undefined HasLayerMgr conditional with HasLayers.
; (HasLayerMgr is actually set for system build. However, since
; this file is included by files like PatchIIROM.a which may not
; be used for system build, the conditional never gets set.) Also
; used new LayerMgr call RedrawAll to refresh screen in SetDepth.
; <41> 12/14/90 SMC Changed DisposeAppPalettes to use ApplZone->bklim to determine
; if palette is in the application heap. With DFH.
; <40> 12/14/90 jmp SetDepth had a problem where the port was NOT being preserved,
; so we (jmp & smc) moved the port preserving code to come just
; before the InitGDevice call. Also, for Layer Manager support,
; we changed the PaintOne/PaintOne sequence to be a
; PaintOne/PaintBehind sequence per dba & vl.
; <39> 10/30/90 DC ngk - Add a check for the basic four-bit grayscale clut in
; CheckColors
; <38> 10/24/90 DC VL - Fix CheckColors to use bit 2 of the value field as an
; inhibit bit instead of an enable bit
; <37> 10/12/90 jmp I put SetDepth back the way it was; it still doesnt work right,
; but I dont have time to mess with it now. Will look into it
; later. Basic problem: thePort is trashed. Bumped version back to
; 2.0.2.
; <36> 10/10/90 jmp Changed SetDepth call to match Monitors; also, updated
; PMgrVersion to 2.0.3 so Monitors could tell when to use SetDepth
; or not.
; <35> 9/23/90 DC csd Fix bug in GetGray when input GDevice is NULL
; <34> 9/17/90 BG Removed <21>. 040s are now behaving more reliably.
; <33> 9/15/90 DC added GetGray and put some quick elimination tests into
; CheckColors
; <32> 8/22/90 DC Added inhibit bit to CheckColors and check for individual max
; tolerance
; <31> 8/20/90 dvb Remove DrawGrayishString
; <30> 8/17/90 gbm The name of grayishTextCopy has changed to grayishTextOr
; <29> 8/7/90 gbm moving SysColors into InitPalettes will get rid of some
; assembler warnings
; <28> 8/3/90 dvb Make setdepth redraw _all_ layers.
; <27> 7/20/90 gbm Warning hunt.
; <26> 7/19/90 DVB Fix stack error in DrawGrayishString
; <24> 7/17/90 DVB Use GetFontInfo instead of FMSwapFont
; <23> 7/14/90 DVB Add "DrawGrayishString"
; <22> 6/28/90 DVB Fix CheckColors
; <21> 6/28/90 BG Added EclipseNOPs to fix temporary flakey 040 problems.
; <20> 6/27/90 DVB Add "CheckColors" dispatch
; <19> 6/19/90 DVB Do Gestalt checking for process mgr, implement pmWhite and
; pmBlack
; <18> 6/15/90 DVB Make ciPrivate always a word, to free up an entry word.
; Get/SetPaletteUpdates. Don't fix color environment on background
; quit.
; <17> 5/17/90 KON Sizes are a word, rather than a long when comparing palette
; sizes in resize palette.
; <16> 3/30/90 DVB Bump PaletteVersion
; <15> 3/29/90 DVB Make "WhatPal" nice, and available to layer mgr.
; <14> 3/2/90 DVB Fix explicit+tolerant+inhibit.
; <13> 2/23/90 DVB Don't clear windowlist in PMgrExit.
; <12> 2/21/90 JS SetDepth also takes a mode...
; <11> 2/15/90 DVB Change SetDepth's return to an OSErr
; <10> 2/14/90 DVB Correct SetDepth's trashage of registers
; <9> 2/5/90 DVB Back-roll the 605 InitGDevice to the BBS master, here. <DVB>
; <8> 1/29/90 DVB Unhilite menu during "SetDepth" call, add rounded corners on
; setdepth
; <7> 1/18/90 DVB Undo last changes
; <6> 1/18/90 DVB Make work with cleaned-up PaletteEqu.a
; <5> 1/17/90 DVB Add PMgr version call, fix unreserveDevices
; <4> 1/12/90 DVB Remove automatic tailpatch to ExitToShell, added SetDepth and
; HasDepth calls.
; <3> 1/2/90 DVB Remove a reference to SysVers, in favor of ForROM
; <1.9> 7/14/89 BAL FOR Aurora: Changed some left shifts to some adds as per gary
; <•2.0> 7/14/89 BAL For Aurora: Final CQD
; <1.8> 7/13/89 BAL Really, dvb, 1.8, fixed SetPal(-1,nil,x).
; <1.7> 7/8/89 BAL Modified PMgrDispatch to skip args of yet-uninvented calls.
; <1.6> 6/28/89 BAL really dvb - ciRGB is valid except for animated entries, where
; <•1.5> 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.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
; 3/30/87 JTC Daisy chain the IAZInit routine properly.
; 3/27/87 EHB window manager calls added
; 3/27/87 AWC interface changed to support window manager
; 2/2/87 AWC new this date
;
; To Do: Make tolerant entries go faster by replacing color2index call with linear search!
; On activatepalette, activate every window from back to front, for total satisfaction!
; Don't forget about InitApp and CleanupApp
; Let DeltaRGB be (R+G+B)/3 or >>2
; Get an invalmenubar!
; PMDithered
; Question: should we call "CheckForProcessMgr" for a ROM version?
; ( instead of calling Gestalt )
; !! Roll in change 14 to the PatchciROM.a file...it was a single BMI.s
; near the top of Correlate.
;
;__________________________________________________________________________________________________
XPalettes PROC EXPORT ; dummy procedure; return to globals AWC.PB457
ENDPROC ; AWC.PB457
IF (&TYPE('ROMPaletteMgr') = 'UNDEFINED') THEN
IF ForROM THEN ; <1.7>
ROMPaletteMgr EQU 1 ; <1.7>
ELSE ; <1.7>
ROMPaletteMgr EQU 0
ENDIF ; <1.7>
ENDIF
IF NOT (ForROM) THEN
JacksonPollack EQU 0
PatchGetCTable EQU 1
PatchInitGDevice EQU 1
HasLayers EQU 1
ELSE ; ForRom
HasLayers EQU 1 ; ROM now has the LayerMgr. <SM5>
ENDIF ; Not ForRom
INCLUDE 'Processes.a'
INCLUDE 'GestaltEqu.a'
INCLUDE 'LayerEqu.a'
AppPalette Equ $DCC ; low memory global for layer palette AWC.PB457
UpdateMask Equ $E000 ; bits used to record update flags in pmPrivate AWC.PB457
AllUpdates Equ $C000 ; combination of CForeBit and CBackBIt AWC.PB457
plttUpdates Equ $0002 ; value passed to SetPalette [short] AWC.PB457
;ctTolBit EQU 5 ; bit in value field saying "I've been yanked"
;ctTolVal EQU $2000
;ctScatterBit EQU 4 ; bit in value field saying "scatter me" <dvb3>
;ctMatchBit EQU 3 ; bit in value field saying "been checked"
;ctScatterVal EQU $1000 ; word-write equivalent of ctScatterBit <dvb3>
;ctReserveBit EQU 6
;ctReserveVal EQU $4000
PMgrVersNum EQU $0202 ; Version number (VVss: version subversion)
;-----------------------------------------------------------
; Let's talk about PMgrVersNum --
;
; The first version with the PMgrVersion call was $0201. This was released
; as 6.0.5.
;
; Version $0202 adds:
; Dispatch #5: WhatPal
; GetPaletteUpdates, SetPaletteUpdates, pmWhite, pmBlack, CheckColors
;-----------------------------------------------------------
; Here is what is left of the Patch Collator stuff. The Palette Manager routines have never
; been patches to the ROM - they were never in the original ROM, so there was nothing to
; patch. This is all there is. The window manager patches are shown below and are marked
; near the routine with another patch signal. To find one, double click on the Patch Name
; and search for that (Command-H under MPW 2.0).
;
; File Date Patch# PMgr Routines Trap#
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (InitPalettes) $AA90
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewPalette) $AA91
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetNewPalette) $AA92
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (DisposePalette) $AA93
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ActivatePalette) $AA94
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetPalette) $AA95
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetPalette) $AA96
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (PmForeColor) $AA97
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (PmBackColor) $AA98
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (AnimateEntry) $AA99
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (AnimatePalette) $AA9A
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetEntryColor) $AA9B
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetEntryColor) $AA9C
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetEntryUsage) $AA9D
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetEntryUsage) $AA9E
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CTab2Palette) $AA9F
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (Palette2CTab) $AAA0
;AppleSystemPatch PaletteMgr.a 22Jul87 #PB222 (CopyPalette) $AAA1
;
; Fix File Date Patch# Fixed Routines Patch Routine Name
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBForeColor) (RGBForeColor)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBBackColor) (RGBBackColor)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB506 (InitMenus) (myInitMenus)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewCWindow) (myNewCWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewWindow) (myNewWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (HiliteWindow) (myHiliteWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MoveWindow) (myMoveWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SizeWindow) (mySizeWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CloseWindow) (myClose)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ShowHide) (myShowHide)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MyExit) (myExit)
;
; Another routine which must be included for proper Palette Manager operation is
; GetNewCWindow which is patched in PatchIIROM.a
;---------------------------------------------------
;
; PROCEDURE ActivatePalette(dstWindow: WindowPtr); INLINE $AA94;
;
; ActivatePalette does what is documented in IM5. UpdatePalette is an internal
; routine that is passed a Palette handle, instead of a window.
PROC
EXPORT ActivatePalette,UpdatePalette
IMPORT CalcDevs,ScatterDevices,SetDev,UnreserveDevices,UpdateDevices
ParamSize equ 4 ; total bytes of params
dstWindow equ ParamSize+8-4 ; source Palette handle
; The ActivatePalette stack frame is defined at the global level so it can be accessed
; by each of the routines subsidiary to ActivatePalette and thereby avoid gross parameter
; passing. All such subsidiary routines will link with A4 and not A6 thus keeping
; ActivatePalette's stack frame intact. D3 is used to hold any error condition.
; It is moved to D0 before we quit.
UpdatePalette
LINK A6,#spVarSize
MOVEM.L D3-D4/A2-A4,-(SP)
MOVEQ #1,D3
CLR.L WindowCopy(A6) ; No top window
MOVE.L PMgrHandle,A2
MOVE.L dstWindow(A6),A3 ; In this case, really, a PaletteHandle
BRA.S FoundPltt ; Jump into middle of ActivatePalette
ActivatePalette
Link A6,#spVarSize ; build stack frame
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
MoveQ #1,D3 ; set error flag in case we branch
Move.L PMgrHandle,A2 ; get global handle
CmpA.L #PMgrNil,A2 ; is it nil?
Beq GoHome ; it has to be initialized
Move.L (A2),A0 ; dereference PMgrHandle AWC.PB500
Move nDevs(A0),D0 ; are there any clut devices? AWC.PB500
Beq GoHome ; no => punt AWC.PB500
Move.L dstWindow(A6),A3 ; get the window pointer
CmpA.L #Nil,A3 ; is it real?
Beq GoHome ; no => go home <AWC/PB150>
Move.L A3,WindowCopy(A6) ; save a copy for those who need it
Tst PortBits+RowBytes(A3) ; is it a new port?
Bpl.S TrySystem ; no => try for a system palette
Move.L GrafVars(A3),A0 ; get the GrafVars handle
Move.L (A0),A0 ; dereference it
Move.L PmFgColor(A0),A3 ; save the palette handle in GrafVars
CmpA.L #Nil,A3 ; is it nil?
Bne.S FoundPltt ; no => we've found it
TrySystem Move.L AppPalette,A3 ; get the layer's palette, if any AWC.PB457
Move.L A3,D0 ; CmpA.L #Nil,A0; is AppPalette nil? AWC.PB457
Bne.S FoundPltt ; no => use AppPalette AWC.PB457
Move.L (A2),A0 ; dereference PMgrHandle
Move.L SysPalette(A0),A3 ; get the system palette, if any
Move.L A3,D0 ; CmpA.L #Nil,A3; is SysPalette nil? AWC.PB457
Beq GoHome ; yes => we can't do it
; past this point we will have locked PMgrHandle and PaletteH. We also save theGDevice
; and clear the InfoHandle variable.
FoundPltt Move.L A2,A0 ; copy PMgrHandle
_HLock ; lock it down
Move.L A3,A0 ; copy PaletteH
MOVE.L A3,PaletteH(A6) ; and save a handle, too
_HLock ; lock it down as well
Move.L (A2),A4 ; dereference PMgrHandle
Move.L A4,PMgrPtr(A6) ; save a copy of the pointer
Move.L PListHandle(A4),A0 ; get PListHandle
_HLock ; lock it down
Move.L (A0),PListPtr(A6) ; save pointer to palette list
Move nDevs(A4),Devices(A6) ; save number of devices in our list
Lea DevHandles(A4),A0 ; point A4 at first device handle
Move.L A0,PDevPtr(A6) ; save pointer to start of device list
Move.L theGDevice,SaveGDev(A6) ; save theGDevice handle
Clr.L InfoHandle(A6) ; mark it as unallocated
Move.L (A3),A4 ; dereference PaletteH
Move.L A4,PalettePtr(A6) ; save it for posterior
Move pmEntries(A4),D4 ; fetch number of entries
Move D4,myEntries(A6) ; save it for posterity
Clr MAnimators(A6) ; MAnimators := 0
Clr MTolerators(A6) ; MTolerators := 0
; Check to see on which devices the window is now rendered
Jsr CalcDevs ; determine the new and frontmost device sets
CLR -(SP) ; No SetEntries
JSR ScatterDevices ; Scatter anyone who needs it <dvb3>
Tst.L FrontSet(A6) ; is this window frontmost on any device?
Beq NoFunStuff ; no => skip our wonderful rendering code
; Count the number of animating and tolerant colors. Mark explicit, dithered, and
; courteous colors as "handled" so we won't bother with them in SetDev et al.
Lea pmInfo(A4),A4 ; point us at the first ColorInfo
MOVE myEntries(A6),D4 ; set up loopy variable
Bra.S ExamEnd ; jump into DBra loop
ExamLoop Move ciUsage(A4),D1 ; copy ciUsage field of current entry
BTst #AnimatedBit,D1 ; pmAnimated?
Beq.S CheckTolrnt ; no => check for other kinds of usage
AddQ #1,MAnimators(A6) ; bump number of animating colors
Bra.S NextColor ; continue
; If a tolerant color is all black or white and not explicit, it's already in the palette, so
; we don't need to add it. We do this by only checking for black or white entries when the entry
; is not explicit. The code later will catch entries that are trying to set the first or last
; colors in the device color table.
CheckTolrnt BTST #TolerantBit,D1
BEQ.S HandleColor
if 0 then
; <SAH 28OCT93>
; I believe this code to be right, however it causes black to be stuck in the palette in many
; cases where it never used to. The net result is that synthetic font caches are built with
; black being odd indices (not ff) and never being flushed once the palette is thrown away.
; We need to figure out how to flush the font caches for real for all processes and then we
; can bring this code back in.
BTST #ExplicitBit,D1 ; is it explicit? <sah 9SEP93>
BNE.S AlwaysAdd ; yes, so we must add it <sah 9SEP93>
endif
MOVE.L ciRGB+red(A4),D0 ; D0: Rhi.Rlo.Ghi.Glo <dvb10>
MOVE.B ciRGB+blue(A4),D0 ; D0: Rhi.Rlo.Ghi.Bhi <dvb10>
TST.L D0 ; Is it all zero's? <dvb10>
BEQ.S HandleColor ; Yes => it's Black, its handled. <dvb10>
ADDQ.L #1,D0 ; =FFFFFF? It's White, its handled <dvb10>
BEQ.S HandleColor ; <dvb10>
AlwaysAdd AddQ #1,MTolerators(A6) ; yes => bump number of tolerant colors
Bra.S NextColor ; continue
HandleColor BSet #HandledBit,ciUsage(A4) ; mark explicit and normal colors as handled
NextColor Add #ciSize,A4 ; bump address to next ColorInfo
ExamEnd DBra D4,ExamLoop ; loop for all pmEntries
; See if we have any animating or tolerant entries. If not, we can skip most of this
Move MAnimators(A6),D0 ; do we have any animating AWC PB223
Or MTolerators(A6),D0 ; or tolerant entries? AWC PB223
Beq NoFunStuff ; no => just clean up the world AWC.PB508
; Allocate a scratch buffer
Move.L #InfoHandSz,D0 ; size of our scratch area AWC
_NewHandle ,CLEAR ; allocate a scratch area
Bne UnlockEm ; we couldn't get it - D3 still says "error" AWC.PB508
Move.L A0,InfoHandle(A6) ; save it
_HLock ; lock it
Move.L (A0),A0 ; dereference it
Move.L A0,InfoPtr(A6) ; save dereferenced ptr
; Call SetDev to render or record the Palette on each device, as appropriate.
MoveQ #0,D4 ; clear device counter
DeviceLoop Move.L FrontSet(A6),D0 ; grab the front device set AWC PB223
BTst D4,D0 ; frontmost on this clut device? AWC PB223
Beq.S NoDevError ; no => jump across SetDev AWC PB223
Move MAnimators(A6),Animators(A6) ; copy MAnimators
Move MTolerators(A6),Tolerators(A6) ; copy MTolerators
Move D4,CurDevice(A6) ; copy it for SetDev
Jsr SetDev ; render palette; did we get an error?
Beq.S NoDevError ; did we find an error?
AddQ #1,D3 ; bump our error count
NoDevError AddQ #1,D4 ; we've examined another device
Cmp Devices(A6),D4 ; have we done them all
Bmi.S DeviceLoop ; no => do another
Move.L SaveGDev(A6),theGDevice ; restore theGDevice handle AWC.PB508
NoFunStuff Move.L PMgrPtr(A6),A0 ; get the PMgrHandle pointer AWC PB223
Move.L PListHandle(A0),A0 ; get the PListHandle
Move.L (A0),A0 ; dereference it
Move.L PalettePtr(A6),A1 ; get the Palette
Move pmPrivate(A1),D0 ; get the entry number
And #PIdMask,D0 ; clear the flag bits
Move Reserves(A0,D0.W*8),D0 ; does this palette have anything reserved?
Beq.S NoneRsrvd ; no => forget about clearing AWC PB223
; Clear any unused devices and update device bitmap
Move.L PMgrPtr(A6),A0 ; get the PMgrHandle pointer AWC PB223
Move.L pmDevices(A1),D0 ; get former device set
Move.L DeviceSet(A6),D1 ; get new device set
Not.L D1 ; complement the current set
And.L D1,D0 ; remove any current bits
Beq.S NoneRsrvd ; if none needing unreserving, quit
JSR UnreserveDevices ; Pass: A0->Pmgr data, A1->palette, D0 = devmask
NoneRsrvd CLR -(SP) ; No Setentries
JSR ScatterDevices ; Scatter those devices that unreserving affected
JSR UpdateDevices
Move.L DeviceSet(A6),pmDevices(A1) ; copy the new device set
SubQ #1,D3 ; if now 0 then we got through with no errors
UnlockEm Move.L PMgrPtr(A6),A0 ; get the master pointer
Move.L PListHandle(A0),A0 ; get this handle
_HUnlock ; unlock it
Move.L A2,A0 ; copy PMgrHandle
_HUnLock
; clear the dirty bit and restore the user's ciUsage fields
Move.L PalettePtr(A6),A0 ; get Palette pointer
BClr #DirtyBit,pmPrivate(A0) ; clear the dirty bit
Move pmEntries(A0),D0 ; fetch number of entries
Lea pmInfo(A0),A0 ; point us at the first ColorInfo
Bra.S UnsetEnd ; jump into DBra loop
UnsetLoop Move ciUsage(A0),D1 ; copy ciUsage field of current entry
And #ClearBits,D1 ; clear all but the user's flags
Move D1,ciUsage(A0) ; restore it
AddA.L #ciSize,A0 ; bump A4 to the next color info
UnsetEnd DBra D0,UnsetLoop ; loop for all pmEntries ColorInfo's
Move.L A3,A0 ; copy PaletteHandle to A0
_HUnlock ; unlock it
Move.L InfoHandle(A6),A0 ; get scratch handle
CmpA.L #Nil,A0 ; was it allocated
Beq.S NoError ; no => don't dispose it
_DisposHandle ; get rid of it
NoError MoveQ #0,D3 ; clear error flag
GoHome Move.L D3,D0 ; copy error flag
MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE Allocate; LOCAL;
;
PMAllocate PROC EXPORT
IMPORT ClaimIndex,FindLink,Pillage,GimmeIndex
; We have one or more animating entries. For each entry in myPalette, look to see if it is
; animating. If so, look to see if it exists on this device. If not, look to see if we can
; allocate it on this device.
MoveM.L D3/D4/A2-A3,-(SP) ; save registers
TST Animators(A6) ; Have anything to animate?
BEQ GoHome
Move.L PalettePtr(A6),A3 ; get palette pointer
MoveQ #0,D4 ; D4 is the entry number
CLR.L D2 ; Clear upper bits of D2, for BF ops
CLR.L D3 ; Clear upper bits of D3, for BF ops
LEA pmInfo(A3),A2 ; bump A2 to the first ColorInfo
Bra.S AnimateEnd ; jump into loop
AnimateLoop Move ciFlags(A2),D0 ; examine "handled"
Bmi.S NextAnimate ; it was explicit or courteous; ignore it
BTst #AnimatedBit,D0 ; are we animating?
Beq.S NextAnimate ; no => ignore it
BTST #ExplicitBit,ciFlags+1(A2) ; is it animated+explicit? <dvb4>
BEQ.S notExplicit ; no, just normal animated... doit. <dvb4>
MOVE D4,D3 ; Move it here, for setting within clutrange
AND BlackIndex(A6),D3 ; Roll over into range
BEQ.S NextAnimate ; Got zero = "white"? So sorry, sir. <dvb4>
CMP BlackIndex(A6),D3 ; are we trying to get "black"? <dvb4>
BEQ.S NextAnimate ; No way, Mr. <dvb4>
BFTST availBits(A6){D3:1} ; This index already explicitly animated?
BNE.S NextAnimate ; Yes! Don't take it a second time.
BFSET availBits(A6){D3:1} ; Mark this explicit entry as used.
Clr -(SP) ; clear index result
Move ciPrivate(A2),-(SP) ; push animation link info (first word only)
Jsr FindLink ; FindLink(Device,myPalette^^.pmInfo[i].ciPrivate)
Move (SP)+,D2 ; pop the index result
Bne.S HadIndex ; true => it's still there - mark it as "handled"
MOVE D3,-(SP) ; we want this index <dvb4>
Jsr Pillage ; steal this index <dvb4>
MOVE D3,D2 ; D2 = index we want (the same for explicit)<dvb4>
BRA.S GotIndex ; And finish with this entry
notExplicit Clr -(SP) ; clear index result
Move ciPrivate(A2),-(SP) ; push animation link info (first word only)
Jsr FindLink ; FindLink(Device,myPalette^^.pmInfo[i].ciPrivate)
Move (SP)+,D2 ; pop the index result
Bne.S HadIndex ; true => it's still there - mark it as "handled"
SUBQ #2,SP ; Space for result
BSR GimmeIndex ; Get the next available index
MOVE (SP)+,D2 ; Did we get a color? Put index in D2
BEQ.S NextAnimate ; No=>but keep looping, for Explicits.
GotIndex MOVE D2,-(SP) ; Push index we want
JSR Pillage ; Knock off anyone else on it.
MOVE D4,D0 ; Set D0 = entry we're stealing for
MOVE.L A2,A0 ; setup for claim
BSR ClaimIndex
HadIndex BSet #HandledBit,ciFlags(A2) ; set "handled" bit
NextAnimate AddA.L #ciSize,A2 ; bump us to the next ColorInfo
AddQ #1,D4 ; bump entry number
AnimateEnd CMP pmEntries(A3),D4 ; At end of entries yet?
BLT AnimateLoop ; loop for all pmEntries
GoHome MoveM.L (SP)+,D3/D4/A2-A3 ; restore registers
Rts ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE CheckAllDeviceCluts;
;
; Set scatterbits for all indices in all devices which
; don't match the correct default clut.
CheckAllDeviceCluts PROC EXPORT
IMPORT CheckDeviceColors
MOVEM.L A0-A3/D3-D4,-(SP) ; save 'em.
MOVE.L PMgrHandle,A2
MOVE.L A2,A0 ; PMgrHandle <dvb5>
_HLock ; Lock it down <dvb5>
MOVE.L (A2),A3 ; Redereference <dvb5>
MOVE nDevs(A3),D3 ; number of devices, for looping <dvb5>
SUBQ #1,D3 ; less one for DBRAing <dvb5>
CLR.L D4 ; D4 = device update mask <dvb5>
gLoop SUB #2,SP ; space for boolean result
MOVE.L DevHandles+DevHandle(A3,D3*8),-(SP) ; push gDevice handle <dvb5>
JSR CheckDeviceColors ; check the device
TST (SP)+ ; Was the device up to date?
BEQ.S gLoopEnd ; Yes=>try next device
BSET D3,D4 ; No=>mark update bit
gLoopEnd DBRA D3,gLoop ; loop for all devices <dvb5>
OR.L D4,scatterDevs(A3) ; mark devices for scattering <dvb5>
MOVE.L A2,A0 ; PMgrHandle
_HUnlock
MOVEM.L (SP)+,A0-A3/D3-D4 ; save 'em.
RTS
;---------------------------------------------------
;
; FUNCTION CheckForProcessMgr:Boolean;
;
; Determine if the process mgr is present using Gestalt.
; (we assume that gestaltLaunchControl iff processMgr is here)
; Affect only A0/D0, since Gestalt is an OS trap.
; return Z-flag Clear if the process mgr is here (BNE ProcMgrTrue)
CheckForProcessMgr PROC EXPORT
MOVE.L #'os ',D0 ; type of question
_Gestalt
TST D0 ; OSErr from Gestalt?
BEQ.S @a ; No=>test result
SUBA A0,A0 ; Yes=>assume there's no procMgr
@a
MOVE.L A0,D0
BTST #gestaltLaunchControl,D0 ; clear the Z-flag if procmgr here
RTS
;---------------------------------------------------
;
; PROCEDURE PMgrExit; AAA2/12;
;
; Someone should call here when an application quits. Please.
;
PMgrExit PROC EXPORT
IMPORT ScatterDevices,UpdateDevices,DisposeAppPalettes
IMPORT CheckForJuggler,CheckForProcessMgr
PXVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result: nothing
return DS.B 4
A6Link DS.B 4 ; old contents of A6
frontPSN DS.B 8 ; a 64-bit process serial number
myPSN DS.B 8 ; likewise
inFront DS.B 2 ; a boolean
IF (forRom OR theFuture) THEN
wList DS.B 4 ; saved window list
ENDIF
linkSize DS.B 0 ; linky number
ENDR
WITH PXVars
LINK A6,#linkSize
TST.B QDExist ; if InitGraf has not been called yet…
BNE.S @doNothing ; (a5) not valid and there is nothing to do
CMP.L #PMgrNil,PMgrHandle ; If the palette manager doesnt exist...
BEQ.S @doNothing
CLR.L AppPalette
JSR DisposeAppPalettes
MOVE.L (A5),A0
BTST #3,QDSpare0(A0) ; Any change to color env?
BEQ.S @doNothing
BSR.S CheckForProcessMgr
BEQ.S @front ; if no process mgr, assume we're in front
MOVE #$0100,inFront(A6) ; default inFront to true
SUBQ #2,SP ; space for result
PEA frontPSN(A6)
_GetFrontProcess
TST (SP)+ ; problem getting front psn?
BNE.S @front ; YES => just zap the cluts
CLR.L myPSN(A6)
MOVE.L #kCurrentProcess,myPSN+4(A6)
SUBQ #2,SP ; space for OSErr result
PEA frontPSN(A6)
PEA myPSN(A6)
PEA inFront(A6)
_SameProcess ; are we the front process?
ADDQ #2,SP ; OSErr leaves inFront true from above
TST inFront(A6)
BEQ.S @doNothing
@front
JSR CheckAllDeviceCluts ; A pretty simple patch, really.
CLR -(SP) ; No Setentries on Scatter
JSR ScatterDevices
2020-05-10 05:37:38 +00:00
BSR.S CheckForJuggler ; Is Jugglertm active?
2019-07-27 14:37:48 +00:00
BNE.S @doNothing ; No=>WMgr is void, next line dangerous
JSR UpdateDevices
MOVE.L mainDevice,theGDevice
@doNothing
IF (forRom OR theFuture) THEN
MOVE.l wList(A6),WindowList ; <SM2> FM restore the current window list
ENDIF
UNLK A6
RTS
;---------------------------------------------------
;
; FUNCTION CheckForJuggler:Boolean;
;
; Set D0 to FFFFFFFF if Juggler is absent, and 00000000 if present. Affect
; No other registers.
CheckForJuggler PROC EXPORT
MOVE.L A0,-(SP) ; stow it.
Move #JugglerTrap,D0 ; #$A88F AWC PB224
_GetTrapAddress ; find out what the trap is
Move.L A0,-(SP) ; save it
Move #UnimplementedTrap,D0 ; #$A89F
_GetTrapAddress ; where do unimplemented traps go
CmpA.L (SP)+,A0 ; are we Juggler™ing?4
SEQ D0 ; D0 = 00 is juggling, FF if not
EXTB.L D0 ; Make it fully big.
MOVEA.L (SP)+,A0 ; It don't hit the CCR.
RTS
;---------------------------------------------------
;
; PROCEDURE RecordPalette(myPalette: PaletteHandle); LOCAL;
;
; Copies myPalette into the PListHandle and records (in the pmPrivate field) where
; it lies in that list. If there are no free spaces in the PListHandle then that
; handle is resized. If it can't be resized, RecordPalette returns an error in D0.
; Otherwise a new handle is allocated for myPalette's pmSeeds field. If one can't
; be allocated, RecordPalette returns an error. It will also return an error if the
; PMgrHandle is nil. If RecordPalette returns an error, it first disposes of
; myPalette so the caller doesn't have to worry about watching the error code.
RecordPalette PROC EXPORT
ParamSize equ 4 ; total bytes of params
myPalette equ ParamSize+8-4 ; source Palette handle
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D3/A2-A4,-(SP) ; save registers
Move.L myPalette(A6),A4 ; get my palette first in case we branch to Error
Move.L PMgrHandle,A2 ; get the PMgrHandle
CmpA.L #PMgrNil,A2 ; has it been initialized?
Beq Error ; no => handle the error (.S won't reach)
Move.L (A2),A0 ; dereference the PMgrHandle
Move.L PListHandle(A0),A3 ; get the handle to the list of palettes
MoveQ #0,D0 ; clear high word
Move SeedHSize(A0),D0 ; get length of seeds handles
_NewHandle ,CLEAR ; allocate it; did we succeed?
Bne Error ; no => handle the error (.S won't reach)
Move.L (A4),A1 ; dereference myPalette
Move.L A0,pmSeeds(A1) ; store the seeds handle in it
Move.L (A2),A1 ; redereference the PMgrHandle
Move FreeSpaces(A1),D0 ; get number of free slots; are any left?
Bne.S FindOne ; yes => don't resize it; search for a free one
MoveQ #0,D3 ; clear high word
Move APalettes(A1),D3 ; get current size
Move.L D3,D0 ; copy it
Add #ListSpace,D0 ; bump it to add more room
Bmi.S Error ; return an error if it wraps
Lsl.L #3,D0 ; multiply by 8
Move.L A3,A0 ; copy PListHandle to A0
_SetHandleSize ; resize it
Bne.S Error ; we couldn't do it
; Now we have to clear all of the new entries we just created.
Move.L A3,A0 ; get PListHandle
Move.L (A0),A0 ; redereference this
Lea (A0,D3.W*8),A0 ; point us at the block to clear
Move.L #ListSpace,D0 ; get how many entries to clear
Bra.S ClearEnd ; jump into loop
ClearLoop Clr.L (A0)+ ; clear the Palette field
Clr.L (A0)+ ; clear the animation field
ClearEnd DBra D0,ClearLoop ; loop for ListSpace entries
AddQ #1,D3 ; D3 is palette's position in PListHandle
Move.L (A3),A0 ; dereference PListHandle
Lea (A0,D3.W*8),A0 ; point A0 at the current position
Move.L (A2),A1 ; redereference the PMgrHandle
Move #ListSpace-1,FreeSpaces(A1) ; number of spaces we've added AWC.PB378
Bra.S Cleanup ; share common code
; We have a free one somewhere in the list. Search forwards until we find one we can use.
; A1 is still pointing at the dereferenced PMgrHandle.
FindOne Move APalettes(A1),D0 ; get number of active handles
Add FreeSpaces(A1),D0 ; calculate total number of entries
MoveQ #0,D3 ; initialize our counter
Move.L (A3),A0 ; dereference PListHandle
Bra.S FindEnd ; jump into loop
FindLoop Move.L PaletteRef(A0),D1 ; get first entry
Beq.S FoundIt ; we've got one
AddQ #PLstEntrySz,A0 ; bump to the next entry
AddQ #1,D3 ; bump our counter
FindEnd DBra D0,FindLoop ; repeat for all spaces
Bra.S Error ; this should not happen
; when we reach this section of common code, A1 = PMgrHandle^, D3 is the position of
; the palette, and A0 points to PListHandle^^[D3]
FoundIt SubQ #1,FreeSpaces(A1) ; decrement the number free
Cleanup AddQ #1,APalettes(A1) ; bump the number used
Move.L A4,PaletteRef(A0) ; record the palette handle in PListHandle
Clr.L Reserves(A0) ; clear the number of entries it reserves
Move.L (A4),A0 ; dereference the Palette
Move pmPrivate(A0),D0 ; grab the current update values AWC.PB457
And #UpdateMask,D0 ; clear away all but the update bits AWC.PB457
Or D0,D3 ; OR palette number with the update bits AWC.PB457
Move D3,pmPrivate(A0) ; this is the number of the palette
MoveQ #0,D0 ; no error
Bra.S GoHome ; we're done-oh!
Error Move.L A4,A0 ; get Palette handle
_DisposHandle ; get rid of it
MoveQ #1,D0 ; set an error
GoHome Tst.L D0 ; set condition codes for return
MoveM.L (SP)+,D3/A2-A4 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; FUNCTION NewPalette(entries: INTEGER; srcColors: CTabHandle; srcUsage,srcTolerance:
; INTEGER) : PaletteHandle; INLINE $AA91;
;
; Allocate a new palette and fill it with information from myColors. Set the usage
; field of each ciInfo to myUsage and set the tolerance to myTolerance. If myColors
; is nil we initialize all the colors to black.
NewPalette FUNC EXPORT
ParamSize equ 10 ; total bytes of params
Palette equ ParamSize+12-4 ; function result
entries equ Palette-2 ; number of entries in Palette
srcColors equ entries-4 ; Color table handle
srcUsage equ srcColors-2 ; default usage for each color in Palette
srcTolerance equ srcUsage-2 ; default tolerance for each color in Palette
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D3/A2,-(SP) ; save registers
Clr.L Palette(A6) ; set the result to nil
Move entries(A6),D3 ; fetch number of entries
MoveQ #0,D0 ; clear it out
Move D3,D0 ; copy it for a calculation
AddQ #1,D0 ; add one for the header
Lsl.L #4,D0 ; multiply by 16
_NewHandle ,CLEAR ; get the handle; did we get an error?
Bne.S GoHome ; yes => we're done for
Move.L A0,A2 ; no => save the handle
Move.L A2,-(SP) ; push handle
Jsr RecordPalette ; allocates a seed's handle and records palette
Bne.S GoHome ; it disposed the palette handle if it failed
; A2 contains the handle to the new Palette. Return the handle, then start by dereferencing it.
; For now we'll just clear everything. Note that we're making use of the fact that
; the size of the header is the same as an entry itself, so we can fall straight
; into the DBra and expect it to clear Entries+1 records! Also, zero the window field
; so we know that this palette is floating
Move.L A2,Palette(A6) ; return the result
Move.L (A2),A0 ; dereference Palette handle
Move D3,pmEntries(A0) ; copy pmEntries
Clr.L pmWindow(A0) ; zero the window field
Move D3,D0 ; get entries into D0
Move srcUsage(A6),D1 ; copy usage to D1
Swap D1 ; put usage into high word
Move srcTolerance(A6),D1 ; put tolerance into low word
Lea pmInfo+ciUsage(A0),A0 ; point A0 at first ColorInfo
Bra.S EntryEnd ; jump into the loop
EntryLoop Move.L D1,(A0) ; set ciUsage (high word) and ciTolerance (low word)
AddA #ciSize,A0 ; bump A0 to the next ciUsage field
EntryEnd Dbra D0,EntryLoop ; loop for all entries
Move.L srcColors(A6),A1 ; get ctabhandle
CmpA.L #Nil,A1 ; is it nil?
Beq.S NoCTab ; yes => skip the copy
Move.L (A1),A1 ; dereference the source color table
Move ctSize(A1),D0 ; get last color table entry
AddQ #1,D0 ; make it number of entries; is it >= 1?
Ble.S NoCTab ; no => we're done
Move.L (A2),A0 ; redereference PaletteHandle
AddA.L #pmInfo+ciRGB+red,A0 ; bump A0 to pmInfo.ciRGB.red
AddA.L #ctTable+rgb+red,A1 ; bump A1 to ctTable.red
; put min(ctSize+1,pmEntries) into D0
Cmp D0,D3 ; compare color table size to palette size
Bge.S UseAsIs ; if D0 is less than D3, we'll use it as is
Move D3,D0 ; copy the lower value into D0
UseAsIs MoveQ #0,D1 ; D1 points at this entry
Bra.S CopyEnd ; jump into loop
CopyLoop Move.L red(A1),red(A0) ; copy red and green
MOVE.B red(A1),red+1(A0) ; and into lo byte of red, <dvb11>
MOVE.B green(A1),green+1(A0) ; and into lo byte of green, <dvb11>
Move blue(A1),blue(A0) ; copy blue
MOVE.B blue(A1),blue+1(A0) ; and into lo byte of blue. <dvb11>
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
CopyEnd Dbra D0,CopyLoop ; loop until the copy is complete
NoCTab MoveQ #0,D0 ; no error
GoHome MoveM.L (SP)+,D3/A2 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; FUNCTION GetNewPalette(paletteID: INTEGER) : PaletteHandle; INLINE $AA92;
;
; GetNewPalette gets a resource of type 'pltt' with the specified ID and clears
; all the private fields. It then returns the data structure as a PaletteHandle.
;
GetNewPalette FUNC EXPORT
ParamSize equ 2 ; total bytes of params
Palette equ ParamSize+12-4 ; function result
paletteID equ Palette-2 ; number of entries in Palette
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L A2,-(SP) ; save registers
Clr.L Palette(A6) ; set result to Nil
; Load the data and detach it from resource manager
Clr.L -(SP) ; make space for result
Move.L #'pltt',-(SP) ; push resource type
Move paletteID(A6),-(SP) ; push resource ID
_GetResource ; get the resource
Move.L (SP)+,D1 ; get handle off the stack
Beq.S GoHome ; if nil we go home
Move.L D1,A2 ; copy it to A2
Move.L D1,-(SP) ; push it back on the stack
_DetachResource ; disconnect from resource manager
Move.L A2,A0 ; copy it for the HNoPurge AWC.PB480
_HNoPurge ; we can't handle purged palettes AWC.PB480
Tst D0 ; did it return an error? AWC.PB480
Bne.S GoHome ; yes => go home AWC.PB480
Move.L (A2),A0 ; dereference palette AWC.PB457
Move #AllUpdates,D1 ; set D1 to the default AWC.PB457
Move plttUpdates(A0),D0 ; get update bits AWC.PB457
Bpl.S NoResUpdate ; the user didn't specify any AWC.PB457
ADD D0,D0 ; put the bits in the correct place AWC.PB457
Move D0,D1 ; put the result into D1 AWC.PB457
NoResUpdate Move D1,pmPrivate(A0) ; put them in the correct place AWC.PB457
Move.L A2,-(SP) ; push the handle
Jsr RecordPalette ; allocates a seeds handle and records palette
Bne.S GoHome ; it disposed the palette handle if it failed
Move.L A2,Palette(A6) ; save Palette in result space
; clear the window field and also the private fields
Move.L (A2),A2 ; dereference it
; Clr.L pmWindow(A2) ; set window field; this palette floats
Clr.L pmDevices(A2) ; clear device bitmap
GoHome Move.L (SP)+,A2 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE ClaimIndex; LOCAL;
;
; Assume that index D2 on CurDevice(A6) is unowned (it was free or has been pillaged).
; Now, we will claim it for palette entry D0 of PalettePtr(A6). We will link it thru
; the Linktabs, mark the Reserve bit in the color table, and zap the seed so that
; no tolerant entries later take it.
;
; In: D0 = Palette entry number
; D2 = device index number
; A0 -> colorinfo field within palette
ClaimIndex PROC EXPORT
MOVE.L DevCTab(A6),A1
MOVE.L (A1),A1 ; A1 -> color table
SUBQ #4,SP
_GetCTSeed ; (changes no registers)
MOVE.L (SP)+,ctSeed(A1) ; alter the seed (we've changed something, eh?)
BSet #HandledBit,ciFlags(A0) ; mark this entry as handled
Move.L ciRGB+red(A0),ctTable+RGB+red(A1,D2.W*8) ; update red and green
Move ciRGB+blue(A0),ctTable+RGB+blue(A1,D2.W*8) ; update blue
AddQ #1,Updates(A6) ; we've changed something
BSet #ctReserveBit,ctTable+value(A1,D2.W*8) ; reserve it
Move.L DevLinks(A6),A1 ; point A1 at LinkTab
And #$7FFF,D0 ; ensure that the top bit is off
Or #$6000,D0 ; set the top bits to 011
Move D0,BackLink(A1,D2.W*4) ; set backward link to entry | $6000
; Calculate a link to this new guy in D0. This will go in ciPrivate and, if we already
; had a link, into the BackLink of the old guy.
Move CurDevice(A6),D0 ; get current device again
Lsl #8,D0 ; shift device into upper byte
Or D2,D0 ; OR in the device number
BSet #15,D0 ; set the three highest bits to 100
; Copy the old link then set the new one. Then look to see if the old link was real.
; If so, we have some work to do. If not, initialize the link by setting the forelink
; to the palette number. The back link has already been set to the entry number.
Move ciPrivate(A0),D1 ; copy the old link
Move D0,ciPrivate(A0) ; point ciPrivate at the new guy
Tst D1 ; did we have any old links?
Bne.S OldLinks ; yes => relink it
Move.L PalettePtr(A6),A0 ; get pointer to palette
Move pmPrivate(A0),D0 ; grab number of this palette
And #PIdMask,D0 ; clear the flag bits
Or #$6000,D0 ; to make it non-zero, set the top bits to 011
Move D0,ForeLink(A1,D2.W*4) ; set forward link to palette | $6000
Bra.S FixRefCount ; fix up the palette
OldLinks Move D1,ForeLink(A1,D2.W*4) ; point Dev[FoundIndex] at old ciPrivate
BfExtU D1{24:8},D2 ; grab index number (0..255)
BfExtU D1{19:5},D1 ; grab device number (0..31)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move.L PMgrPtr(A6),A1 ; get base pointer
AddA.L #LinkTabs,A1 ; bump it to the LinkTabs
Move D0,BackLink(A1,D1.L*4) ; set the backward link
FixRefCount Move.L PListPtr(A6),A0 ; get PListPtr
Move.L PalettePtr(A6),A1 ; get palette
Move pmPrivate(A1),D0 ; get palette number
And #PIdMask,D0 ; clear the flag bits
AddQ #1,Reserves(A0,D0.W*8) ; bump number of reserves
ADDQ #1,updates(A6) ; we've made a change
RTS
;---------------------------------------------------
;
; PROCEDURE ClearPalette(cPalette: PaletteHandle); LOCAL;
;
; Release all animated entries owned by cPalette.
;
ClearPalette PROC EXPORT
IMPORT ClearStrand
ParamSize equ 4 ; total bytes of params
cPalette equ ParamSize+8-4 ; source Palette handle
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D2-D4/A2-A4,-(SP) ; save registers
Move.L PMgrHandle,A3 ; get palette manager handle
CmpA.L #PMgrNil,A3 ; are we initialized?
Beq.S GoHome ; no => quit AWC.PB377
Move.L (A3),A3 ; dereference it
Move.L cPalette(A6),A1 ; get palette handle AWC.PB457
Move.L (A1),A2 ; dereference it AWC.PB457
; Examine and remember the number of reserves this palette still has. Clear the number.
Move pmPrivate(A2),D0 ; get the number of this palette
And #PIdMask,D0 ; clear away update bits
Move.L PListHandle(A3),A0 ; get the palette list handle
Move.L (A0),A0 ; dereference it
CmpA.L PaletteRef(A0,D0.W*8),A1 ; is this the correct handle? AWC.PB462
Bne.S BadPalette ; no => don't dispose anything AWC.PB462
Move Reserves(A0,D0.W*8),D3 ; remember how many animating entries it has
Clr.L Reserves(A0,D0.W*8) ; clear the count
; Now clear each of the seeds this palette knows about, so that we'll update if we
; become active again.
Clr.L pmDevices(A2) ; clear devices field
Move.L pmSeeds(A2),A0 ; get seeds handle
Move.L (A0),A0 ; dereference it
Move SeedHSize(A3),D0 ; get size of handle
Lsr #2,D0 ; divide by 4
Bra.S SeedEnd ; start clear loop
SeedLoop Clr.L (A0)+ ; clear the remembered seed
SeedEnd DBra D0,SeedLoop ; do it again
; Now check to see if we have any animating entries which we can dispose
Tst D3 ; were there any animating entries?
Beq.S GoHome ; no => quit
; run through every color to make sure it is not reserving any entries on any device
; by examining what the PaletteManager has to say about this palette as well as what
; each entry's ciPrivate field has to say about the subject. Leave pmPrivate field
; (which tells PMgr which palette we ought to be) alone.
Move pmEntries(A2),D0 ; get number of entries
AddA.L #pmInfo,A2 ; bump A2 to the first ColorInfo
Lea DevHandles(A3),A4 ; point A4 at PMgrDevices
AddA.L #LinkTabs,A3 ; point A3 to LinkTabs
Bra.S EntryEnd ; jump into loop
EntryLoop Move ciPrivate(A2),D3 ; get the current link information
Bpl.S NextEntry ; if positive it's not a link
Jsr ClearStrand ; If it's a link, wipe out it and its successors. <dvb3>
OR.L D4,scatterDevs-LinkTabs(A3) ; A tricky offset; set bits to scatter devices <dvb3>
NextEntry Clr ciFlags(A2) ; shut down any crap
Clr ciPrivate(A2) ; clear it
AddA.L #ciSize,A2 ; bump A2 to the next ColorInfo
EntryEnd DBra D0,EntryLoop ; loop for all pmEntries
GoHome MoveQ #0,D0 ; clear error condition
BadPalette MoveM.L (SP)+,D2-D4/A2-A4 ; restore registers AWC.PB457
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE ClearStrand(Linkhead); LOCAL;
;
; Clear all device indexes which start on the given strand, taken from
; a ciPrivate field. Mark bit 4 of the value field of indices which must
; be returned to the environment.
; Enter with D3 = the linkhead, A3 = Linktab base, A4 = gDevice list base
; return with D4 = bitmask of those devices needing scattering
; We'll stomp on A0,D1,D2,D3,D4
; (this code was moved out of ClearPalette so others could call it <dvb3>)
ClearStrand PROC EXPORT
CLR.L D4 ; no devices need scattering yet.
LinkLoop BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Move.L DevHandle(A4,D1.W*8),A0 ; get the device handle
Move.L (A0),A0 ; dereference it
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),A0 ; get handle to CTab
Move.L (A0),A0 ; dereference CTab
Cmp ctSize(A0),D2 ; is index number <= entries - 1?
Bhi.S IgnoreIt ; no => don't unreserve it
MOVE #ctScatterVal,ctTable+value(A0,D2.W*8) ; unreserve it, mark scatterbit <dvb3>
BSET D1,D4 ; mark device for scattering <dvb3>
IgnoreIt Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A3,D1.L*4),A0 ; point A0 at next forward link
Move ForeLink(A0),D3 ; get next link
Clr.L ForeLink(A0) ; clear it for the next guy
LinkEnd Tst D3 ; is there another link to examine?
Bmi.S LinkLoop ; yes => go unlink it
GoHome Rts
;---------------------------------------------------
;
; PROCEDURE ErasePalette(ePalette: PaletteHandle); LOCAL;
;
ErasePalette PROC EXPORT
ParamSize equ 4 ; total bytes of params
ePalette equ ParamSize+8-4 ; PaletteHandle to dispose
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L A2-A3,-(SP) ; save registers
Move.L ePalette(A6),A3 ; get the handle
Move.L (A3),A2 ; dereference it
Move.L pmSeeds(A2),A0 ; get the seeds handle while we have it
CmpA #Nil,A0 ; is it nil?
Beq.S DontDispose ; yes => punt
_DisposHandle ; it's gone
DontDispose Move.L WindowList,A0 ; get the window list for this layer AWC.PB506
Bra.S ListLoop ; continue AWC.PB439
CheckWindow Tst PortBits+Rowbytes(A0) ; by chance is it an old window? AWC.PB439
Bpl.S IgnoreWind ; yes => ignore it AWC.PB439
Move.L GrafVars(A0),A1 ; get GrafVars handle AWC.PB439
Move.L (A1),A1 ; dereference it AWC.PB439
Move.L PmFgColor(A1),D0 ; get the palette AWC.PB439
Cmp.L ePalette(A6),D0 ; is it correct? AWC.PB439
Bne.S IgnoreWind ; no => don't clear it AWC.PB439
Clr.L PmFgColor(A1) ; mark the window as Paletteless AWC.PB439
IgnoreWind Move.L nextWindow(A0),A0 ; grab the next window AWC.PB439
ListLoop Move.L A0,D0 ; CmpA.L #Nil,A0; another window? AWC.PB439
Bne.S CheckWindow ; yes => keep looking AWC.PB439
CmpA.L AppPalette,A3 ; are we disposing AppPalette? AWC.PB508
Bne.S NotAppPltt ; no => whew! AWC.PB508
Clr.L AppPalette ; okay, we won't try to find it anymore AWC.PB508
NotAppPltt Move pmPrivate(A2),D0 ; grab the last field we need from A2 AWC.PB439
And #PIdMask,D0 ; clear away flag bits
Move.L PMgrHandle,A2 ; get the main handle
CmpA.L #PMgrNil,A2 ; is it nil?
Beq.S GoHome ; yes => don't try to find it
Move.L (A2),A2 ; dereference it
Move APalettes(A2),D1 ; start with number of active palettes
Add FreeSpaces(A2),D1 ; add free spaces to get length of list
Cmp D1,D0 ; are we within the correct range?
Bpl.S GoHome ; no => punt
Move.L PListHandle(A2),A1 ; get handle to list of palettes
Move.L (A1),A1 ; dereference it
CmpA.L (A1,D0.W*8),A3 ; get this handle; do they match?
Bne.S GoHome ; no => in the future we may scan for it; for now, punt
Clr.L (A1,D0.W*8) ; it's no longer referenced
AddQ #1,FreeSpaces(A2) ; add 1 to free spaces
SubQ #1,APalettes(A2) ; subtract 1 from total palettes
GoHome MoveM.L (SP)+,A2-A3 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE Correlate; LOCAL;
;
; Make sure we have sufficient colors for all Tolerant entries.
; We use the bit table (availbits) to make sure that we don't
; yank the same entry twice, or steal an animated explicit.
Correlate PROC EXPORT
IMPORT Pillage,DeltaRGB,GimmeIndex
MOVEM.L D3-D7/A2-A3,-(SP)
TST Tolerators(A6) ; Anything intolerant?
BEQ Leave ; No. Bail.
;
; First, we'll snag any explicit tolerant entries.
;
MOVEQ #0,D4 ; entry number we're examining
MOVE.L PalettePtr(A6),A2 ; A2->our palette
LEA pmInfo(A2),A2 ; A2->first colorInfo
MOVE.L DevCTab(A6),A3 ; A3 = device colortable handle
MOVE.L A3,A0 ; A0 gets handle
_HLock ; Lock it down
MOVE.L (A3),A3 ; A3-> device colortable
CLR.L D3 ; Clear the upper bits, for BF ops
ExplLoop MOVE ciUsage(A2),D7 ; D7 = usage of this entry
BMI.S ExplLoopEnd ; Already handled?
BTST #TolerantBit,D7 ; A Tolerator?
BEQ.S ExplLoopEnd ; No, try next
BTST #ExplicitBit,D7 ; Explicit Tolerator?
BEQ.S ExplLoopEnd ; No, try next
MOVE D4,D3 ; D3 = palette entry
AND BlackIndex(A6),D3 ; D3 = explicit-ized clut index
BEQ.S ExplLoopEnd ; Don't take index zero! it's white, you know.
CMP BlackIndex(A6),D3 ; Are trying to snag black?
BEQ.S ExplLoopEnd ; No! No! No!
BFTST availBits(A6){D3:1} ; Already taken (by exp-anim, or earlier exp-tol)?
BNE.S ExplLoopEnd
BFSET availBits(A6){D3:1} ; No! Mark it as taken!
MOVE D3,-(SP) ; This is the index we want to steal
JSR Pillage ; Make sure noone else is settin on it
SUBQ #2,SP ; Space for colordelta result
PEA ciRGB(A2) ; Push palette's desired color
PEA ctTable+rgb(A3,D3*8) ; Push current device's color
bsr.l DeltaRGB ; How far apart are we?
MOVE (SP)+,D1
CMP ciTolerance(A2),D1 ; are we within tolerance?
BLS.S @GoodColor ; Yes=>don't change its RGB
LEA ctTable(A3,D3*8),A0 ; A0->colorspec we're doing
MOVE.L ciRGB+red(A2),rgb+red(A0) ; copy palette's red,green into device
MOVE ciRGB+blue(A2),rgb+blue(A0) ; copy palette's blue into device
BSET #ctTolBit,value(A0) ; Set the tolerator bit for index
SUB #4,SP ; space for result
_GetCTSeed ; put new seed
MOVE.L (SP)+,ctSeed(A3) ; into table
ADDQ #1,updates(A6) ; We've made a device change
@GoodColor BSET #HandledBit,ciFlags(A2) ; Mark entry as handled
ExplLoopEnd ADD #ciSize,A2 ; Bump A2 to next colorInfo in our palette
ADDQ #1,D4 ; D4 is next entry number
CMP myEntries(A6),D4 ; Up to, and not including, number of entries
BLT.S ExplLoop
ExplDone
;Now, we'll snag any regular tolerant entries.
MOVE.L PalettePtr(A6),A2 ; A2->our palette
LEA pmInfo(A2),A2 ; A2->first colorInfo
;Walk thru each palette entry and make sure there's an index within tolerance.
CLR.L D7 ; Clear upper bits of D7, for BF ops
CLR.L D4 ; D4 = palette entry number, and flags in high bits
MOVE BlackIndex(A6),D5 ; when looking for indices, start at D5 and work down.
SnagLoop TST ciFlags(A2) ; has this entry been handled?
BMI SnagLoopEnd ; yah.
BTST #TolerantBit,ciUsage+1(A2) ; Is it a tolerator?
BEQ SnagLoopEnd ; nah.
MOVE ciTolerance(A2),D6 ; get tolerance, for later
CMPI #33,Tolerators(A6) ; If a smallish number of tolerators,
BLT.S CheckColor ; Take slow C2I case.
BTST #31,D4 ; Until one entry missed, take slow C2I case.
BEQ.S CheckColor
CMP #$400,D6 ; if tol<$400, just find one (instead of lots of color-to-indexes with new itables)
BLS.S GrabIndex ; Go grab it.
CheckColor SUBQ #4,SP ; space for Color2Index result
PEA ciRGB(A2) ; push pointer to rgb
_Color2Index
MOVE.L (SP)+,D7 ; D7 = closest match
SUBQ #2,SP ; DeltaRGB result
PEA ciRGB(A2) ; Push palette's rgb
PEA ctTable+rgb(A3,D7*8) ; Push closest-match rgb
bsr.l DeltaRGB
CMP (SP)+,D6 ; Compare delta to ciTolerance
BHS.S SnagIt ; Low enough, just mark it handled and go on to take index.
BFTST availBits(A6){D7:1} ; Out of range, but is it owned?
BEQ.S YankIt ; If not, we'll take that entry.
;We must find an index to yank to our color.
GrabIndex SUBQ #2,SP
BSR GimmeIndex ; Get the next available index
MOVE (SP)+,D7 ; D7 = next so-called available index
BEQ.S GoHome ; Zero means we're out of entries
BFTST availBits(A6){D7:1} ; Have we already matched to it?
BNE.S GrabIndex ; If so, we can't just use it.
PillIt MOVE D7,-(SP) ; Pillage this entry
JSR Pillage
YankIt LEA ctTable(A3,D7*8),A0 ; A0->colorSpec we're grabbing
MOVE.L ciRGB+red(A2),rgb+red(A0) ; Yank our index's red,green
MOVE ciRGB+blue(A2),rgb+blue(A0) ; Yank our index's blue
BSET #ctTolBit,value(A0) ; Mark it as tolerance-yanked
SUB #4,SP ; space for result
_GetCTSeed ; put new seed
MOVE.L (SP)+,ctseed(A3) ; into table
ADDQ #1,updates(A6) ; We've made changes
BSET #31,D4 ; We've made changes anyway, we can snag quickly.
SnagIt BFSET availBits(A6){D7:1} ; Mark this index as taken
SnagLoopEnd ADD #ciSize,A2 ; Bump A2 to next colorinfo
ADDQ #1,D4 ; Advance D4 to next entry
CMP myEntries(A6),D4 ; Done yet?
BNE SnagLoop
GoHome MOVE.L DevCTab(A6),A0 ; Get handle
_HUnlock ; Release it
Leave MOVEM.L (SP)+,D3-D7/A2-A3
RTS
;---------------------------------------------------
;
; PROCEDURE DisposeAppPalettes();
;
; Look through the palette list and dispose of any in the current App heap.
DisposeAppPalettes PROC EXPORT
MOVEM.L A0-A3/D0-D3,-(SP) ; save all registers
MOVE.L PMgrHandle,A2 ; get paletteMgr handle
CMP.L MinusOne,A2 ; is it there?
BEQ GoHome ; => no, just return
MOVE.L (A2),A1 ; point to data structure
MOVE.L PListHandle(A1),A0 ; get handle to palette list
_HLock ; and lock it down
MOVE.L (A0),A3 ; point to palette list
Move APalettes(A1),D3 ; get number of active handles
Beq.s NoPals ; no friends => go home
Add FreeSpaces(A1),D3 ; calculate total number of entries
;<13> Clr.L WindowList ; clear the list of windows for FrontWindow AWC.PB506
BRA.S FindEnd ; => check for no entries
FindLoop Move.L PaletteRef(A3),D1 ; get first entry
BEQ.S FindNext ; => no palette in entry
MOVE.L ApplZone,A0 ; get application heap zone <41>
CMP.L A0,D1 ; Are we before the heap zone? <41>
BLO.S FindNext ; Yes => not in app heap
CMP.L bklim(A0),D1 ; Are we past the heap zone <41>
BHS.S FindNext ; => not in app heap
MOVE.L D1,-(SP) ; push palette handle
_DisposePalette ; and dispose it in place
FindNext AddQ #PLstEntrySz,A3 ; bump to the next entry
FindEnd DBra D3,FindLoop ; repeat for all spaces
NoPals MOVE.L (A2),A1 ; point to palette stuff
MOVE.L PListHandle(A1),A0 ; get handle to palette list
_HUnlock ; and unlock it
GoHome Clr.L AppPalette ; set us up for the next guy AWC.PB508
MOVEM.L (SP)+,A0-A3/D0-D3
RTS
;---------------------------------------------------
;
; PROCEDURE DevSetEntries(aGDev:GDeviceHandle);
;
; Pass a gDev handle in A0. A SetEntries is made with the device's own color table.
; The device's seed isn't changed, though.
DevSetEntries PROC EXPORT
MOVE.L A2,-(SP) ; save one register
MOVE.L TheGDevice,-(SP) ; save current gDev
MOVE.L (A0),A2 ; A2->gDev
MOVE.L gdPMap(A2),A2 ; A2 = pixmapH
MOVE.L (A2),A2 ; A2->pixmap
MOVE.L pmTable(A2),A2 ; A2 = cTabH
MOVE.L (A2),A2 ; A2->colortable
MOVE.L ctSeed(A2),-(SP) ; save seed til after SetEntries
MOVE.L A0,TheGDevice ; set to our important one
Clr -(SP) ; push starting count of 0 for SetEntries
Move ctSize(A2),-(SP) ; push number of entries-1
Pea ctTable(A2) ; push address of the first ColorSpec
_SetEntries ; do it
MOVE.L (SP)+,ctSeed(A2) ; restore seed
MOVE.L (SP)+,TheGDevice ; restore gDev
MOVE.L (SP)+,A2 ; restore register
RTS
;---------------------------------------------------
;
; PROCEDURE DisposePalette(srcPalette: PaletteHandle); INLINE $AA93;
;
DisposePalette PROC EXPORT
ParamSize equ 4 ; total bytes of params
srcPalette equ ParamSize+8-4 ; PaletteHandle to dispose
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L A2,-(SP) ; save registers
Move.L srcPalette(A6),A2 ; get the handle
CmpA.L #Nil,A2 ; is it nil?
Beq.S GoHome ; yes => go home
Move.L A2,-(SP) ; push handle
Jsr ClearPalette ; release any animating entries
Bne.S GoHome ; if nonzero the palette was bad AWC.PB457
Move.L A2,-(SP) ; push it again
Jsr ErasePalette ; erase palette from PMgrHandle and its window
Move.L A2,A0 ; fetch palette handle into A0
_DisposHandle
GoHome MOVE.L (SP)+,A2 ; restore register
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; FUNCTION GetClut(aGDev:gDeviceHandle):handle; Local;
;
; return a handle of an appropriate default clut for the device passed.
; This'll be unlocked, purgeable.
PROC
EXPORT GetClut
GCVars RECORD {A6Link},DECREMENT
result DS.B 4 ;Result: Handle to clut
aGDev DS.B 4 ;Input: device handle
return DS.B 4
A6Link DS.B 4 ;old contents of A6
oldZone DS.B 4 ;zone, upon entering
typeNumber DS.B 2
linkSize DS.B 0 ;linky number
ENDR
whichClut DC.B 0,1,2,3,4,0,0,5,6 ; Which cluthandle to use
; depth 1 2 2 4 4 8 8
; color? x n y n y n y
clutIDs DC.B $01,$22,$42,$24,$44,$28,$08
WITH GCVars
GetClut LINK A6,#linkSize
MOVEM.L A0-A1/D0-D3,-(SP)
_GetZone ; Save old heap zone,
MOVE.L A0,oldZone(A6) ; To restore upon exit.
MOVE.L SysZone,A0
_SetZone ; But we'll use the system heap.
MOVE.L aGDev(A6),A0
MOVE.L (A0),A0
MOVE.L gdPMap(A0),A1
MOVE.L (A1),A1
MOVE pmPixelSize(A1),D0
CMPI #1,D0 ; one bit?
BEQ.S @bw ; can only be black&white
BTST #0,gdFlags+1(A0) ;A color device?
BEQ.S @bw ; no? pixelSize is good enough
ADDQ #1,D0
@bw LEA whichClut-1,A1 ; A1->which cluthandle to use
MOVE.B (A1,D0.W),D0 ; Get byte sized offset, D0 hibits clr
MOVE D0,typeNumber(A6) ; save number 0-6 for clut type
MOVE.L PMgrHandle,A0 ; A0 = the big handle
MOVE.L (A0),A0 ; A0->PMgr
MOVE.L sevenCluts(A0,D0*4),A0 ; A0 = old Handle for this spot
MOVE.L A0,D1 ; Is it NIL?
BEQ.S @getCTab ; Yes, we'll have to get one
MOVE.L (A0),D1 ; Is it Purged?
BEQ.S @tossAndGet ; Yes => lose old handle, get new one
MOVE.L A0,result(A6) ; No => we had the last one we made
BRA.S @nilResult ; we'll return it.
@tossAndGet _DisposHandle
MOVE typeNumber(A6),D0
@getCTab LEA clutIDs,A0 ; A0->table of clut resource ID's
CLR.L D3 ; Zap upper bytes
MOVE.B (A0,D0.W),D3 ; Get byte-sized morsel into D0, high bits clear
SUBQ #4,SP ; Room for result
MOVE D3,-(SP) ; Push resource ID
_GetCTable
MOVE.L (SP)+,A0 ; Handle in A0
MOVE.L A0,result(A6) ; Get that result into our result
BEQ.S @nilResult ; Problem?
MOVE.L (A0),A1 ; A1->our new clut
CMP.L ctSeed(A1),D3 ; Does the seed match the ID?
BNE.S @purgeIt ; No=>can't be a ROM resource
SUBQ #4,SP
MOVE.L #'clut',-(SP)
MOVE D3,-(SP)
MOVE.L A0,D3 ; We'll keep old one in D3 a moment
MOVE #$FFFF,RomMapInsert
_Get1Resource ; Get only a ROMish version of clut-D3
MOVE.L (SP)+,D2 ; Get anything?
BEQ.S @useOld ; No=>go deal with old one
MOVE.L D2,result(A6) ; Yes=>save this one,
MOVE.L D3,A0 ; lose the old one
_DisposHandle
BRA.S @gotIt
@useOld MOVE.L D3,A0
@purgeIt _HPurge ; No, so mark it purgeable
@gotIt MOVE.L PMgrHandle,A0 ; And save the handle.
MOVE.L (A0),A0 ; A0->PMgrData
MOVE typeNumber(A6),D0 ; D0 = selection, 0-5
MOVE.L result(A6),sevenCluts(A0,D0*4) ; And save the handle.
@nilResult MOVE.L oldZone(A6),A0 ; Now, restore previous zone.
_SetZone
@goHome MOVEM.L (SP)+,A0-A1/D0-D3
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
; PROCEDURE InitPalettes; INLINE $AA90;
;
PROC
IMPORT RecordPalette,CHECKALLDEVICECLUTS
IMPORT SCATTERDEVICES,UpdateDevices
EXPORT InitPalettes
EXPORT SysColors,SysColorEnd
SysColorCount EQU 2
SysColors DC.W $0000,$0003,$0000,$000F ; seed [long], transIndex [word], ctSize [word]
DC.W $0000,$FFFF,$FFFF,$FFFF ; white
DC.W $0001,$0000,$0000,$0000 ; black
SysColorEnd EQU *
VarSize equ 0
InitPalettes
Link A6,#VarSize ; build stack frame
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
; Start by running down the device list, finding all active CLUT devices. Count how many
; there are and record them in PListHandle.
Move.L PMgrHandle,D0 ; get the Palette Manager handle
Cmp.L #PMgrNil,D0 ; is it nil?
Bne ChkAppPltt ; we're initializaed - check for AppPalette AWC.PB520
; To start things up, allocate enough room for static Palette Manager data and 32 device table
; slots. Note that the current implementation of Color Quickdraw (not the architecture) sets
; a limit on the color index model of 256 entries. THIS NUMBER IS ASSUMED BY THE CODE BELOW,
; but the structure will allow modification once 'clut's bigger than 256 entries are allowed.
; This code also assumes that the cards have the potential of being 256 entry cards even if
; set at a lower resolution, so it always allocates 256 entries in each device map (integer sized).
; Note - the total space allocated for pm device table space is presumed (below) to
; be long word aligned. See the loop below at Clearing.
Move.L #PMgrDataSz,D4 ; set D4 to the required size AWC.PB500
Move.L D4,D0 ; copy size to D0
_NewHandle ,SYS,CLEAR ; allocate our data area in the system heap
Bne GoHome ; we got an error, so we quit
Move.L A0,A3 ; copy to A3 for later use
Move.L A0,PMgrHandle ; and remember it in low memory
MoveQ #0,D3 ; zero our device count
Move.L (A3),A4 ; dereference PMgrHandle
CLR.L scatterDevs(A4) ; no devices needing scatter, to start <dvb3>
CLR.L updateDevs(A4) ; no devices needing scatter, to start <dvb3>
AddA #DevHandles,A4 ; point A4 at our local device list
Clr.L -(SP) ; push room for device handle AWC.PB500
_GetDeviceList ; get the start of the device list AWC.PB500
Move.L (SP)+,A2 ; put the device list in A2 AWC.PB500
Bra.S DeviceEnd ; jump to the end of the loop AWC.PB500
DeviceLoop Move.L (A2),A0 ; dereference device handle
Move gdFlags(A0),D0 ; get flags; is it an active device?
; Bpl.S NextDevice ; no => examine next device ;Yes, we do. <dvb>
BTst #ScreenDevice,D0 ; is it a screen device?
Beq.S NextDevice ; no => examine next device AWC.PB377
; three lines commented out: we list non-cluts in case they become clut. dvb1
; Move gdType(A0),D0 ; get the type of the device AWC.PB377
; Cmp #ClutType,D0 ; is it a Clut device?
; Bne.S NextDevice ; no => we only track Clut devices
AddQ #1,D3 ; yes => bump our device count by 1
Move.L A2,DevHandle(A4) ; copy device handle AWC.PB500
Clr.L DevFrontMost(A4) ; clear device FrontMost field
AddQ #DevInfoSz,A4 ; bump A4 to the next device slot
Add.L #256*PmDevSz,D4 ; each device table is 1024 bytes (for now)
Cmp #DevLimit,D3 ; are we at the limit the PMgr can handle? AWC.PB500
Bpl.S EnoughDevs ; if so, we'll ignore any remaining devices
NextDevice Move.L gdNextGD(A0),A2 ; grab next device AWC.PB500
DeviceEnd Move.L A2,D0 ; CmpA #Nil,A2; is it nil? AWC.PB500
Bne.S DeviceLoop ; no => let's do it again
EnoughDevs Move.L (A3),A4 ; redereference PMgrHandle
Move D3,nDevs(A4) ; save length of device list
Move D3,D0 ; make a copy of D3
Bne.S SeedSizeOk ; make sure we have a minimum size seed AWC.PB500
AddQ #1,D0 ; a kludge, but it's easier this way AWC.PB500
SeedSizeOk Lsl #2,D0 ; multiply by 4 AWC.PB500
Move D0,SeedHSize(A4) ; save size of SeedHSize handle
Clr APalettes(A4) ; no animating palettes yet
Move #ListSpace,FreeSpaces(A4) ; 16 free slots; we'll add more if needed
Move.L D4,D0 ; D4 is the required size of PMgrHandle
Move.L A3,A0 ; put handle in A0 for the call
_SetHandleSize ; and expand the handle up
Bne.S ResizeFails ; it went badly
Move.L #ListSpace,D0 ; start with initial space for handles
Lsl #3,D0 ; multiply by 8
_NewHandle SYS,CLEAR ; allocate and clear the handle
Beq.S ClearAll ; if it works, continue
Move.L A3,A0 ; prepare to dispose the handle
_DisposHandle ; get rid of it
ResizeFails Move.L #PMgrNil,PMgrHandle ; it didn't work - zero the handle
Bra GoHome ; head home with error in D0 AWC.PB508
ClearAll Move.L (A3),A4 ; redereference PMgrHandle
Move.L A0,PListHandle(A4) ; save the list of handles
Move.L A3,A0 ; put PMgrHandle into A0
_HLock ; lock it down
MOVE.L (A3),A4 ; redereference
LEA sevenCluts(A4),A0 ; A0->list of depth-cluts
MOVEQ #6,D0 ; A loop counter
@sclclr CLR.L (A0)+ ; Clear one handle
DBRA D0,@sclclr
Move D3,D0 ; get the number of devices
Lsl #8,D0 ; multiply by 1024/4 (1024 per device/4 per CLR.L)
Lea PMgrDataSz(A4),A0 ; calculate start of device links
Bra.S ClearEnd ; jump into loop
ClearLoop Clr.L (A0)+ ; clear a long word - see! long word aligned
ClearEnd DBra D0,ClearLoop ; repeat for all long words
Move.L theZone,-(SP) ; save the current zone
Move.L SysZone,theZone ; set the system zone
Clr.L -(SP) ; clear some space for a handle
Clr -(SP) ; push PaletteId = 0
_GetNewPalette ; try to get the system palette
Move.L (SP)+,SysPalette(A4) ; save it; was it nil?
Bne.S NoError ; no => we're done
Lea SysColors,A0 ; get a pointer to our default table
Move.L #SysColorEnd-SysColors,D0 ; get size
_PtrToHand ; make a handle out of it
Move.L A0,D3 ; save it
Clr.L -(SP) ; space for result
Move #SysColorCount,-(SP) ; push the number of entries
Move.L A0,-(SP) ; push our handle
Move #pmCourteous,-(SP) ; all courteous entries
Move #$0000,-(SP) ; reasonably tolerant entries, too
_NewPalette ; let's call ourselves to get a new palette
Move.L (SP)+,SysPalette(A4) ; save the palette; we sure hope we got one
Move.L D3,A0 ; put handle back in A0
_DisposHandle ; snuff it
NoError Move.L SysPalette(A4),A0 ; get the palette for a moment
CmpA.L #Nil,A0 ; is there one?
Beq.S Cleanup ; no => cleanup
Move.L (A0),A0 ; dereference SysPalette
BSet #CForeBit,pmPrivate(A0) ; set the system update bits
BSet #CBackBit,PmPrivate(A0)
Cleanup Move.L (SP)+,theZone ; restore the current zone
Move.L A3,A0 ; get PMgrHandle
_HUnlock ; unlock it
JSR CheckAllDeviceCluts ; Let PMgr slam the device cluts
MOVE #$1,-(SP) ; Set the palette with new colors
JSR ScatterDevices ; Redistribute them clut indices
Clr.L AppPalette ; clear the applications's palette AWC.PB457
Bra.S LookForIt ; jump ahead AWC.PB520
; Notice that we rely upon AppPalette being initialized (or -1) every time we arrive here. If
; it is non-zero, we assume this is an extra call to InitPalettes so we just leave.
ChkAppPltt Move.L AppPalette,D0 ; fetch AppPalette; is it nil? AWC.PB520
Beq.S LookForIt ; yes => look for a palette resource 0 AWC.PB508
AddQ.L #1,D0 ; bump it by 1; was it $FFFFFFFF? AWC.PB508
Bne ChkAppPEnd ; no => must be good; next thing AWC.PB520
CLR.L AppPalette ; clear the AppPalette AWC.PB508
LookForIt Tst CurApRefNum ; are we using the system resource file? AWC.PB469
Beq.S ChkAppPEnd ; yes => forget installing an AppPalette AWC.PB520
Clr -(SP) ; function result AWC.PB457
_CurResFile ; get the current resfile AWC.PB457
Move (SP)+,D3 ; put it in D3 AWC.PB457
Cmp CurApRefNum,D3 ; need we change it? AWC.PB457
Beq.S ResFileOkay ; no => we've already got it AWC.PB457
Move CurApRefNum,-(SP) ; push the refnum back AWC.PB457
_UseResFile ; use this resfile AWC.PB457
Clr -(SP) ; result word AWC.PB506
_ResError ; see if this worked AWC.PB506
Move (SP)+,D0 ; get the result AWC.PB506
Bne.S ChkAppPEnd ; quit if we didn't get it AWC.PB520
ResFileOkay Clr.L -(SP) ; function result AWC.PB457
Move.L #'pltt',-(SP) ; push the resource type AWC.PB457
Clr -(SP) ; id 0 AWC.PB457
_Get1Resource ; fetch an application palette, if any AWC.PB457
Move.L (SP)+,A2 ; get handle off the stack AWC.PB457
Move.L A2,D0 ; CmpA.L #Nil,A2; did we get a resource? AWC.PB457
Beq.S Cleanup2 ; if nil we go home AWC.PB457
Move.L A2,-(SP) ; push it for the DetachResource AWC.PB457
_DetachResource ; disconnect from resource manager AWC.PB457
Move.L (A2),A0 ; dereference palette AWC.PB457
Move #AllUpdates,D1 ; set D1 to the default AWC.PB457
Move plttUpdates(A0),D0 ; get update bits AWC.PB457
Bpl.S NoResUpdate ; the user didn't specify any AWC.PB457
ADD D0,D0 ; put the bits in the correct place AWC.PB457
Move D0,D1 ; put the result into D1 AWC.PB457
NoResUpdate Move D1,pmPrivate(A0) ; put them in the correct place AWC.PB457
Move.L A2,-(SP) ; push palette for the RecordPalette AWC.PB457
Jsr RecordPalette ; allocates seeds handle, records palette AWC.PB457
Bne.S Cleanup2 ; it disposed palette if failed AWC.PB457
Move.L A2,AppPalette ; copy it to AppPalette AWC.PB457
Move.L (A2),A0 ; dereference AppPalette AWC.PB457
BSet #DisposeBit,pmPrivate(A0) ; set for automatic disposal AWC.PB457
Clr.L pmDevices(A0) ; clear device bitmap AWC.PB457
Cleanup2 Cmp CurApRefNum,D3 ; did we change the current resfile? AWC.PB457
Beq.S ChkAppPEnd ; no => don't put it back AWC.PB457
Move D3,-(SP) ; push the old current resfile AWC.PB457
_UseResFile ; and restore the old one AWC.PB457
ChkAppPEnd
CheckExit
JSR UpdateDevices
GoHome MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
Unlk A6 ; clear stack frame
Rts ; go home
;---------------------------------------------------
;
; FUNCTION CheckDeviceColors(aGDev:gdHandle):Boolean; LOCAL;
;
; Looks at a (hopefully clut) device, and compare its clut to the
; default clut for that device. If even one entry which is not owned for animation
; is out of place, the whole clut is marked for scattering. Return TRUE if
; the device is now marked for scattering.
CheckDeviceColors PROC EXPORT
CDCVars RECORD {A6Link},DECREMENT
result DS.B 2 ;Result: boolean
aGDev DS.B 4 ;Input: device handle
return DS.B 4
A6Link DS.B 4 ;old contents of A6
linkSize DS.B 0 ;linky number
ENDR
WITH CDCVars
LINK A6,#linkSize
MOVEM.L A0-A3/D0-D2,-(SP)
CLR D2 ; D2 = on-the-fly bool result.
MOVE.L aGDev(A6),A2
MOVE.L (A2),A3 ; A3->gDevice
TST gdType(A3) ; a clut device? <dvb5>
BNE.S GoHome ; No=> go home w/false
TST gdFlags(A3) ; Device active?
BPL.S GoHome ; No=> ditto
SUBQ #4,SP ; space for result <dvb5>
MOVE.L A2,-(SP) ; push gDevice handle <dvb5>
JSR GetClut ; get the appropriate default clut <dvb5>
MOVE.L (SP)+,A0 ; A0 = handle to default clut, keep handle on stk
MOVE.L (A0),A0 ; A0->default clut <dvb5>
LEA ctTable+rgb(A0),A0 ; bump to first colorSpec's rgb fiel <dvb5>
MOVE.L gdPMap(A3),A1 ; A1 = device's pixmap <dvb5>
MOVE.L (A1),A1 ; A1->device's pixmap <dvb5>
MOVE.L pmTable(A1),A1 ; A1 = device's clut <dvb5>
MOVE.L (A1),A1 ; A1->device's clut <dvb5>
MOVE ctSize(A1),D0 ; D0 = size of clut - 1 <dvb5>
LEA ctTable(A1),A1 ; bump A1 to first colorSpec <dvb5>
iLoop BTST #reserveBit,value(A1) ; is this entry reserved? <dvb5>
BNE.S iLoopEnd ; yes, skip it <dvb5>
BSET #ctMatchBit,value(A1) ; mark entry as looked at
MOVE.L red(A0),D1 ; get default red,green
CMP.L rgb+red(A1),D1 ; do red and green match default? <dvb5>
BNE.S fixIt ; No, scatter all the indices <dvb5>
MOVE blue(A0),D1 ; Get default blue
CMP rgb+blue(A1),D1 ; match device blue? <dvb5>
BEQ.S iLoopEnd ; No, scatter... <dvb5>
fixIt BSET #ctScatterBit,value(A1) ; Mark index for scattering <dvb5>
MOVEQ #-1,D2 ; Set D2 result to true
iLoopEnd ADDA #8,A0 ; Bump A0 to next colorSpec <dvb5>
ADDA #8,A1 ; Bump A1 to next colorSpec <dvb5>
DBRA D0,iLoop ; loop for all indices <dvb5>
GoHome MOVE D2,result(A6) ; Set result.
MOVEM.L (SP)+,A0-A3/D0-D2
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
; FUNCTION FindLink(LinkInfo:integer):integer; LOCAL;
;
; FindLink searches the device links until it encounters a device that matches Device or
; until it reaches the end of the list. It returns the index if it finds one. It
; returns 0 (which is an illegal index since it matches white) if it can't find one.
FindLink PROC EXPORT
ParamSize equ 2 ; total bytes of params
theIndex equ ParamSize+10-2 ; index result
LinkInfo equ theIndex-2 ; this palette's key to previously reserved entries
VarSize equ 0
Link A4,#VarSize ; build stack frame
Move.L D3,-(SP) ; save a register
; We will use D3 as a watchdog counter. We set it to the maximum number of devices that we
; might have to search so that if things go very wrong we stand a chance of finding out about it.
Clr theIndex(A4) ; set result to "illegal"
Move LinkInfo(A4),D0 ; get link data
BfExtU D0{16:3},D1 ; grab top 3 bits
Cmp #4,D1 ; are they set correctly
Bne.S GoHome ; no => the LinkInfo is invalid
Move Devices(A6),D3 ; get number of devices
Move.L PMgrPtr(A6),A0 ; PMgrHandle^
AddA.L #LinkTabs,A0 ; calculate start of LinkTabs
Bra.S IndexEnd ; start watchdog loop
IndexLoop BfExtU D0{19:5},D1 ; grab device number (0..31)
BfExtU D0{24:8},D2 ; grab index number (0..255)
Cmp CurDevice(A6),D1 ; is it this device?
Beq.S FoundIt ; yes => we've got it
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move (A0,D1.L*4),D0 ; get next link; is the top bit set?
Bpl.S GoHome ; no => stop because we ran out of tries
IndexEnd DBra D3,IndexLoop ; examine another index until our watchdog runs out
; Our watchdog counter ran out, so something is terribly wrong. We'll be polite about it and
; say we were just unable to find it.
Bra.S GoHome
; We found the index. Set true and return the appropriate index to theIndex(A4)
FoundIt And #$00FF,D2 ; clear everything except the index
Move D2,theIndex(A4) ; set the result
GoHome Move.L (SP)+,D3 ; restore registers
Unlk A4 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE AnalyzeDev; LOCAL;
;
; Build, into the InfoPtr, a sequence of entries to steal. The priorities are
; as follows: Any explicit entries are available for explicating. Any free
; entries are first available. Any yanked-tolerant entries are available next.
; Any animated entries owned by other palettes are available last.
; One more thing: the secondary sorting on 1,2,4-bit devices is by index, and on
; 8-bit devices is by nibble-swapped index. Thus, and this is especially
; important on gray-scale cluts, the indices
; will be stolen in a somewhat spread-out manner.
AnalyzeDev PROC EXPORT
MOVEM.L A2-A3/D3-D5,-(SP)
LEA availBits(A6),A2 ; A2->availBits. Permanently.
MOVE.L DevCTab(A6),A3 ; A3 = handle to current dev's clut
MOVE.L (A3),A3 ; A3 -> current dev's clut. Permanently.
CLR.L D3 ; Clear upper bits of D3, for BF op
MOVE BlackIndex(A6),D3 ; D3 = highest index. Permanently.
CLR D4 ; D4 = number of indices put into list.
BSR ClearAvailBits ; Start the bits az nilz.
;
; First, find and unavailable-ize any
; eplicit entries from our palette.
;
MOVE.L PalettePtr(A6),A0 ; A0->our palette
CLR.L D0 ; D0 = each entry number, starting zero
CLR.L D2 ; Clear upper bits of D2, for BF ops
LEA pmInfo(A0),A1
BRA.S @expEnd
@expLoop MOVE ciFlags(A1),D1 ; D1 = usage for the entry
BMI.S @expNext ; Handled-bit->set!
BTST #explicitBit,D1 ; An explicit entry?
BEQ.S @expNext
MOVE D0,D2 ; Copy entry number.
AND D3,D2 ; And it down into clut's range
BFSET (A2){D2:1} ; Set the used bit in our array o' bits
@expNext ADDA #ciSize,A1 ; Bump A1 to next colorinfo
ADDQ #1,D0 ; Bump D0 to match it's index
@expEnd CMP pmEntries(A0),D0 ; Done last one yet?
BLO.S @expLoop ; No, do more.
;
; Add any fully open indices to our list.
;
MOVE.L InfoPtr(A6),A1 ; A1->our list o' entries.
MOVE D3,D0 ; D0 will do our walking
CLR.L D1 ; Clear upper bits of D1, for BF ops
@openLoop MOVE D0,D1 ; D1=our possibly scrambled index
BTST #4,D3 ; 8-bit device?
BEQ.S @openNot8 ; No, don't spread entries
ROR.B #4,D1 ; Yes => swap hi,lo nibbles
@openNot8 BFTST (A2){D1:1} ; This entry already taken?
BNE.S @openNext ; Yes => try next
MOVE ctTable+value(A3,D1*8),D2 ; Get the status of index D1
AND #ctReserveVal+ctTolVal,D2 ; Mask out the bits we need to check
BNE.S @openNext ; Either bit set is a problem, cant use it
BFSET (A2){D1:1} ; Mark it as taken
MOVE D1,(A1,D4*2) ; Put index into list.
ADDQ #1,D4 ; One more in list.
@openNext DBRA D0,@openLoop ; Keep checking, right down to zero.
;
; Add any non-reserved (inanimate) indices to our list.
;
MOVE D3,D0 ; D0 will do our walking
@inAniLoop MOVE D0,D1 ; D1=our possibly scrambled index
BTST #4,D3 ; 8-bit device?
BEQ.S @inAniNot8 ; No, don't spread entries
ROR.B #4,D1 ; Yes => swap hi,lo nibbles
@inAniNot8 BFTST (A2){D1:1} ; This entry already taken?
BNE.S @inAniNext ; Yes => try next
BTST #ctReserveBit,ctTable+value(A3,D1*8) ; This index anim?
BNE.S @inAniNext ; Yes: not for us.
BFSET (A2){D1:1} ; Mark it as taken
MOVE D1,(A1,D4*2) ; Put index into list.
ADDQ #1,D4 ; One more in list.
@inAniNext DBRA D0,@inAniLoop ; Keep checking, right down to zero.
;
; Add any reserved indices which aren't ours to our list.
; This is called Seriously Pillaging.
;
MOVE pmPrivate(A0),D5 ; D5 = palette number plus some bits
AND #pIDMask,D5 ; D5 = palette number.
Move.L PMgrPtr(A6),A0 ; A0 = base pointer
AddA.L #LinkTabs,A0 ; A0->dem linky tings
MOVE D3,D0 ; D0 will do our walking
@pillLoop MOVE D0,D1 ; D1=our possibly scrambled index
BTST #4,D3 ; 8-bit device?
BEQ.S @pillNot8 ; No, don't spread entries
ROR.B #4,D1 ; Yes => swap hi,lo nibbles
@pillNot8 BFTST (A2){D1:1} ; This entry already taken?
BNE.S @pillNext ; Yes => try next
; No=> walk the linktabs, see if it's ours
MOVE CurDevice(A6),D2 ; D2 = device number we're checking
LSL #8,D2 ; Device number in upper bits
MOVE.B D1,D2 ; Index in lower byte
@findOwner AND #$1FFF,D2 ; Clear key bits
MOVE.W foreLink(A0,D2*4),D2 ; Get the forelink
BEQ.S @pillNext
BMI.S @findOwner
AND #$1FFF,D2 ; Okay, clear the key bits
CMP D2,D5 ; Is this index owned by this palette
BEQ.S @pillNext ; Yes: not for us.
BFSET (A2){D1:1} ; Mark it as taken
MOVE D1,(A1,D4*2) ; Put index into list.
ADDQ #1,D4 ; One more in list.
@pillNext DBRA D0,@pillLoop ; Keep checking, right down to zero.
MOVE D4,Pillages(A6) ; This is how many we've got
Clr Histogram(A6) ; This is how many we've used
BSR.S ClearAvailBits ; Clear the bits array to nothing again.
MOVEM.L (SP)+,A2-A3/D3-D5
RTS
ClearAvailBits
MOVEQ #7,D0
@a CLR.L availBits(A6,D0*4)
DBRA D0,@a
BFSET availBits(A6){0:1} ; set the bit for white
BFSET availBits(A6){D3:1} ; set the bit for black
RTS
;---------------------------------------------------
;
; PROCEDURE Pillage(myChoice); LOCAL;
;
; Just clear the links for index myChoice on CurDevice(A6)
; No registers altered.
Pillage PROC EXPORT
PilVars RECORD {A4Link},DECREMENT
result DS.B 0 ;result: none
myChoice DS.B 2 ;input: index to pillage
return DS.B 4
A4Link DS.B 4 ;old contents of A4
linkSize DS.B 0 ;linky number
ENDR
WITH PilVars
LINK A4,#linkSize
MoveM.L D0/D3/D4,-(SP) ; save registers
MOVE myChoice(A4),D3 ; does the caller want a specific index?
MOVE CurDevice(A6),D4
LSL #8,D4 ; shift device into upper bits
MOVE.B D3,D4 ; put index into low bits
MOVE D4,-(SP)
_ZapLinks ; unlink index D3 of CurDevice(A6)
MOVE.L DevCTab(A6),A0 ; A0 = current device's clut
MOVE.L (A0),A0 ; A0->clut
CLR ctTable+value(A0,D3*8) ; Unmark the clut index entirely
GoHome MoveM.L (SP)+,D0/D3/D4 ; restore registers
Unlk A4 ; clear stack frame
Rtd #result-return-4 ; strip parameters and go home
;---------------------------------------------------
;
; FUNCTION GimmeIndex:INTEGER; LOCAL;
;
; Judging from the infohandle, get the next available index. Return
; zero if there's none left. We assume the ActivatePalette stack frame.
; We'll make use of registers D0,D1, and A0.
;
GimmeIndex PROC EXPORT
CLR D1 ; our result
MOVE Histogram(A6),D0 ; D0 = next item from infoptr to steal
CMP Pillages(A6),D0 ; Taken as many as we can?
BEQ.S @goHome ; Return nil.
MOVE.L infoPtr(A6),A0 ; A0->list of indices to take
MOVE (A0,D0*2),D1 ; D1 = next one off list
ADDQ #1,Histogram(A6) ; Bump to next guy
@goHome MOVE D1,4(SP) ; return index
RTS
;---------------------------------------------------
;
; PROCEDURE MarkDevUBit; LOCAL;
;
; Set bit CurDevice in updateDevs.
MarkDevUBit PROC
Move CurDevice(A6),D0 ; get current device
MOVE.L PMgrPtr(A6),A0 ; A1->PMgr data
MOVE.L updateDevs(A0),D1 ; tricky offset, get device update mask
BSET D0,D1 ; set the device's bit for updating
MOVE.L D1,updateDevs(A0) ; put back mask
RTS
IF NOT ROMPaletteMgr THEN
;---------------------------------------------------
;
; FUNCTION DeltaRGB(RGB1,RGB2:RGBColor):integer; LOCAL;
;
; A cool routine which preserves all registers
DeltaRGB FUNC EXPORT
ParamSize equ 8 ; total bytes of params
Delta equ ParamSIze+10-2 ; integer result
RGB1 equ Delta-4 ; palette entry pointer
RGB2 equ RGB1-4 ; color table entry pointer
VarSize equ 0 ; size of variables
Link A6,#VarSize ; build stack frame
MOVEM.L A0-A1/D0-D1,-(SP)
Move.L RGB1(A6),A0 ; get first RGBColor
Move.L RGB2(A6),A1 ; get second RGBColor
Move (A1)+,D0 ; grab index red
Sub (A0)+,D0 ; subtract entry red
Bhs.S NotNeg1 ; take abs(Index.Red-ColorInfo.Red)
Neg D0 ; negate it
NotNeg1 Move (A1)+,D1 ; grab index green
Sub (A0)+,D1 ; subtract entry green
Bhs.S NotNeg2 ; take abs(Index.Green-ColorInfo.Green)
Neg D1 ; negate it
NotNeg2 Cmp D0,D1 ; leave greater unsigned value in D0
Blo.S DontSwitch1 ; D1 < D0 => D0 is already greater
Move D1,D0 ; green value is greater
DontSwitch1 Move (A1),D1 ; grab index blue
Sub (A0),D1 ; subtract entry blue
Bhs.S NotNeg3 ; take abs(Index.Blue-ColorInfo.Blue)
Neg D1 ; negate it
NotNeg3 Cmp D0,D1 ; leave greater unsigned value in D0
Blo.S FixResult ; D1 < D0 => D0 is already greater
Move D1,D0 ; blue value is greater
FixResult Move D0,Delta(A6) ; set result
MOVEM.L (SP)+,A0-A1/D0-D1
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
ENDF
ENDIF
;---------------------------------------------------
;
; PROCEDURE RedrawDesktop; LOCAL;
;
; Ignoring things like "DeskHook"... Just paint the rectangle pointed to by A2 on the desktop.
; We'll use A3 in the process.
RedrawDesktop PROC EXPORT
SUBQ #4,SP ; space for new region
_NewRgn
MOVE.L (SP),A3 ; A3 = new region, leave stack copy
MOVE.L A2,-(SP) ; Push device rectangle
_RectRgn ; Make that rectangular region
CLR.L -(SP) ; NIL = desktop area
MOVE.L A3,-(SP) ; Push the device region
_PaintOne ; Update desktop within device bounds
MOVE.L A3,-(SP) ; Get rid of our temp region
_DisposRgn
RTS
;---------------------------------------------------
;
; PROCEDURE DirtySeeds(dstPalette: PaletteHandle); LOCAL;
;
DirtySeeds PROC EXPORT
ParamSize equ 4 ; total bytes of params
dstPalette equ ParamSize+8-4 ; destination Palette handle
VarSize equ 0 ; size of variables
Link A6,#VarSize ; build stack frame AWC.PB508
Move.L PMgrHandle,A0 ; get the PMgrHandle (we assume its safe) AWC.PB508
Move.L (A0),A0 ; dereference it AWC.PB508
Move SeedHSize(A0),D0 ; get the seed handle size AWC.PB508
Lsr #2,D0 ; divide it by 4 to get number of longs AWC.PB508
SubQ #1,D0 ; decrement it for the DBra loop AWC.PB508
Move.L DstPalette(A6),A0 ; get the palette AWC.PB508
Move.L (A0),A0 ; dereference it AWC.PB508
BSet #DirtyBit,pmPrivate(A0) ; set the dirty bit AWC.PB508
Move.L pmSeeds(A0),A0 ; get the seeds handle AWC.PB508
Move.L (A0),A0 ; dereference it AWC.PB508
ClearLoop Clr.L (A0)+ ; clear a seed AWC.PB508
DBra D0,ClearLoop ; continue AWC.PB508
GoHome Unlk A6 ; clear stack frame AWC.PB508
Rtd #ParamSize ; strip parameters and go home AWC.PB508
;---------------------------------------------------
;
; PROCEDURE SetPalette(dstWindow: WindowPtr; srcPalette: PaletteHandle; CUpdates: BOOLEAN);
; INLINE $AA95;
;
; Passing -1 for the window sets the App Palette to the palette specified.
SetPalette PROC EXPORT
ParamSize equ 10 ; total bytes of params
dstWindow equ ParamSize+8-4 ; source Palette handle
srcPalette equ dstWindow-4 ; new window, if any
CUpdates equ srcPalette-2 ; whether we want background color updates
VarSize equ 0 ; size of variables
Link A6,#VarSize ; build stack frame
MOVE.L D3,-(SP)
Move.L PMgrHandle,A1 ; we have to be initialized
CmpA.L #PMgrNil,A1 ; is it initialized?
Beq GoHome ; no => punt
Move.L dstWindow(A6),A0 ; get the window pointer
CmpA.L #-1,A0 ; does the caller want to set AppPalette?
Bne.S NotSystem ; no => go look for the window
Move.L AppPalette,D0 ; get the application palette; is it nil? AWC.PB457
Beq.S NoAppPltt ; yes => don't dispose it AWC.PB457
Move.L D0,A0 ; put it in an address register AWC.PB457
Move.L (A0),A0 ; dereference it AWC.PB457
BTst #DisposeBit,pmPrivate(A0) ; should we clobber it? AWC.PB457
Beq.S NoAppPltt ; no => the caller deals with it AWC.PB457
Move.L D0,-(SP) ; push the palette AWC.PB457
_DisposePalette ; can you say "bye bye"? AWC.PB457
NoAppPltt Move.L SrcPalette(A6),A0 ; get the palette parameter AWC.PB457
Move.L A0,AppPalette ; set the layer palette; is it nil? AWC.PB457
Beq.S AppNil ; no => activate the layer palette AWC.PB457
MOVE.L (A0),A0 ; A0->Palette
BSet #CBackBit,PmPrivate(A0) ; set background update bit AWC PB223
BSet #CForeBit,PmPrivate(A0) ; set foreground update bit AWC PB223
Move.L SrcPalette(A6),A0 ; get the palette parameter AWC.PB457
BRA.S AppNotNil
AppNil Move.L (A1),A0 ; dereference PMgrHandle <dvb15 1.8>
Move.L SysPalette(A0),A0 ; get the system palette AWC.PB457
Move.L A0,D0 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
Beq GoHome ; yes => shouldn't happen, but quit anyway AWC.PB457
AppNotNil Move.L A0,-(SP) ; push the palette pointer AWC.PB508
Bsr DirtySeeds ; clear the device seeds so we'll update AWC.PB508
Clr.L -(SP) ; push function result AWC.PB439
_FrontWindow ; push the front window AWC.PB439
Bra.S DontClear ; activate it AWC PB223
NotSystem Tst PortBits+RowBytes(A0) ; is it a new port?
Bpl.S GoHome ; if not, we're out of here
Move.L srcPalette(A6),D0 ; get the palette handle
Move.L GrafVars(A0),A1 ; get handle to GrafVars
Move.L (A1),A1 ; dereference GrafVars
Move.L PmFgColor(A1),D3 ; save whatever's there currently
Move.L D0,PmFgColor(A1) ; store the palette in GrafVars.PmFgColor; is it nil?
Beq.S BitsOkay ; yes => that's okay, but we won't dereference it
Move.L D0,A1 ; put the Palette handle into A1
Move.L (A1),A1 ; dereference it
; Move.L A0,pmWindow(A1) ; store the window in the palette AWC.PB439
BClr #CBackBit,PmPrivate(A1) ; clear background update bit AWC PB223
BSet #CForeBit,PmPrivate(A1) ; set foreground update bit AWC PB223
Tst.B CUpdates(A6) ; does she want background updates? AWC PB223
Beq.S BitsOkay ; 0 => default case, CUpdates = false AWC PB223
Bpl.S AllowBacks ; 1 => CUpdates = true AWC PB223
BTst #NForeBit,CUpdates(A6) ; does he want foreground updates? AWC PB223
Bne.S YesFores ; yes => leave it as is AWC PB223
BClr #CForeBit,PmPrivate(A1) ; turn foreground updates off AWC PB223
YesFores BTst #NBackBit,CUpdates(A6) ; does she want background updates? AWC PB223
Beq.S BitsOkay ; no => skip it AWC PB223
AllowBacks BSet #CBackBit,PmPrivate(A1) ; set the foreground update bit AWC PB223
BitsOkay Cmp.L D0,D3 ; are they identical? AWC PB223
Beq.S GoHome ; don't bother activating anything
Move.L A0,-(SP) ; push the window pointer for the activate palette
Tst.L D3 ; is this nil?
Beq.S DontClear ; don't clear it
MOVE.L D3,-(SP)
JSR UpdatePalette ; Get rid of reserved entries, if necessary
Move.L D3,A0 ; copy it to an address register AWC.PB457
Move.L (A0),A0 ; dereference it AWC.PB457
BTst #DisposeBit,pmPrivate(A0) ; should we dispose it? AWC.PB457
Beq.S DontClear ; no => leave it alone AWC.PB457
Move.L D3,-(SP) ; push the old handle
_DisposePalette ; can you say "bye bye"? I knew you could AWC.PB457
DontClear _ActivatePalette ; set the palette if it happens to be FrontWIndow
GoHome MOVE.L (SP)+,D3
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; FUNCTION GetPalette(srcWindow: WindowPtr) : PaletteHandle; INLINE $AA96;
;
GetPalette PROC EXPORT
ParamSize equ 4 ; total bytes of params
GetResult equ ParamSize+12-4 ; result palette handle
srcWindow equ GetResult-4 ; source window to help find the palette
VarSize equ 0 ; size of variables
Link A6,#VarSize ; build stack frame
Clr.L GetResult(A6) ; clear the result handle
Move.L PMgrHandle,A1 ; we have to be initialized
CmpA.L #PMgrNil,A1 ; is it initialized?
Beq.S GoHome ; no => punt
Move.L srcWindow(A6),A0 ; get the window pointer
CmpA.L #Nil,A0 ; is it real?
Beq.S GoHome ; no => punt
CmpA.L #-1,A0 ; do they want the system palette?
Bne.S NotSystem ; no, not the system
Move.L AppPalette,GetResult(A6) ; grab AppPalette; is it nil? AWC.PB457
Bne.S GoHome ; no => we're done AWC.PB457
Move.L (A1),A1 ; dereference PMgrHandle AWC.PB457
Move.L SysPalette(A1),A0 ; get SysPalette AWC.PB457
Move.L A0,D0 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
Beq.S GoHome ; yes => how did this happen? oh well, quit AWC.PB457
_HandToHand ; make a copy of it AWC.PB457
Tst D0 ; did the call succeed? AWC.PB457
Bne.S GoHome ; no => go home with result nil AWC.PB457
Move.L A0,AppPalette ; now we'll use the copy AWC.PB457
Move.L A0,GetResult(A6) ; give them the copy's handle AWC.PB457
Move.L A0,-(SP) ; push the handle for RecordPalette AWC.PB457
Move.L (A0),A0 ; dereference it AWC.PB457
Clr.L pmSeeds(A0) ; kill the copy of the seeds handle AWC.PB457
BClr #DisposeBit,pmPrivate(A0) ; caller must now dispose it AWC.PB457
Jsr RecordPalette ; insert it into our list of known things AWC.PB457
Beq.S GoHome ; scurry out of here AWC.PB457
Clr.L AppPalette ; sorry, it failed AWC.PB457
Clr.L GetResult(A6) ; so clear the result, too AWC.PB457
Bra.S GoHome ; continue AWC.PB457
NotSystem Tst PortBits+RowBytes(A0) ; is it a new port?
Bpl.S GoHome ; if not, we're out of here
Move.L GrafVars(A0),A0 ; get handle to GrafVars
Move.L (A0),A0 ; dereference GrafVars
Move.L PmFgColor(A0),A0 ; get the palette AWC.PB457
Move.L A0,GetResult(A6) ; give it to the caller; is it nil? AWC.PB457
Beq.S GoHome ; yes => don't bother with the dispose flag AWC.PB457
Move.L (A0),A0 ; dereference it AWC.PB457
BClr #DisposeBit,PmPrivate(A0) ; turn off the auto dispose AWC.PB457
GoHome Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE FindIndex; IMMEDIATE;
;
; On entry:
; A2 - Palette pointer
; A3 - ColorInfo
;
; On exit:
; D0 - index of animating entry; 0 if not found (0 is illegal for animation)
FindIndex PROC EXPORT
MoveM.L D3/D4,-(SP) ; save registers
Move ciPrivate(A3),D0 ; get link info
BfExtU D0{16:3},D1 ; grab top 3 bits
Cmp #4,D1 ; are they set correctly
Bne.S BadIndex ; no => the LinkInfo is invalid
Move.L PMgrHandle,A0 ; get main handle
CmpA.L #PMgrNil,A0 ; is it nil?
Beq.S BadIndex ; yes => punt
Move.L (A0),A0 ; dereference the palette manager
Move nDevs(A0),D3 ; get number of devices to search in D3
Beq.S BadIndex ; no devices => can't animate AWC.PB500
Lea DevHandles(A0),A1 ; point A1 at the device info stuff
Bra.S DevEnd ; jump into loop
DevLoop Move.L DevHandle(A1,D3.W*8),D4 ; get device handle
Cmp.L theGDevice,D4 ; is this it?
Beq.S FoundDevice ; yes => continue
DevEnd DBra D3,DevLoop ; no => look at another device
Bra.S BadIndex ; we fell through - punt
FoundDevice Move nDevs(A0),D4 ; get number of devices, this time as a watchdog
AddA.L #LinkTabs,A0 ; bump A0 to the base of LinkTabs
Bra.S IndexEnd ; start watchdog loop
IndexLoop BfExtU D0{19:5},D1 ; grab device number (0..31)
BfExtU D0{24:8},D2 ; grab index number (0..255)
Cmp D3,D1 ; is it this device?
Beq.S FoundIndex ; yes => we've got it
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move ForeLink(A0,D1.L*4),D0 ; get next link; is the top bit set?
Bpl.S BadIndex ; no => stop because we ran out of tries
IndexEnd DBra D4,IndexLoop ; examine another index until our watchdog runs out
BadIndex Bra.S SetBadIndex ; set index to "illegal" AWC.PB377
; We found the index. Ensure that we don't exceed the bit depth, set "true" by returning
; a value <> 0.
FoundIndex And #$00FF,D2 ; clear everything except the index
Move D2,D0 ; set the result AWC.PB377
Move.L theGDevice,A0 ; get theGDevice AWC.PB377
Move.L (A0),A0 ; dereference it AWC.PB377
Move.L gdPMap(A0),A0 ; get handle to pixmap AWC.PB377
Move.L (A0),A0 ; dereference pixmap AWC.PB377
Move.L pmTable(A0),A0 ; get handle to CTab AWC.PB377
Move.L (A0),A0 ; dereference color table AWC.PB377
Cmp ctSize(A0),D0 ; compare link to maximum index AWC.PB377
Blt.S GoHome ; if D0-ctSize <= 0 then cool AWC.PB480
SetBadIndex MoveQ #0,D0 ; set index to "illegal" white AWC.PB377
GoHome MoveM.L (SP)+,D3/D4 ; restore registers
Rts ; go home
;---------------------------------------------------
;
; FUNCTION Entry2Index(srcEntry: INTEGER):LONGINT; AAA2/0
;
; Return long index of specified entry of thePort's palette, on theGDevice.
; If none, return black, and return a QDErr.
; Mostly, rely on Color2Index to do the picking for us. We'll override its
; choice for an animated or explicit entry on an appropriate device.
Entry2Index PROC EXPORT
EIVars RECORD {A6Link},DECREMENT
result DS.B 4 ;Result: Longword index
srcEntry DS.B 2 ;Input: entry in palette of current port
return DS.B 4
A6Link DS.B 4 ; old contents of A6
srcPalette DS.B 4 ; The palette we're working on.
linkSize DS.B 0 ; linky number
ENDR
WITH EIVars
LINK A6,#linkSize
MoveM.L A2-A3,-(SP) ; save registers
MOVE #1,QDErr ; Default: error
CLR.L result(A6) ; Default: white. Or maybe black.
Move.L PMgrHandle,D0 ; get the main handle, are we initialized?
Beq GoHome ; no => punt AWC.PB377
Move.L GrafGlobals(A5),A0 ; get the QuickDraw globals pointer
Move.L ThePort(A0),A0 ; point at the port
Tst PortBits+Rowbytes(A0) ; is it a new port?
Bpl GoHome ; no => punt AWC.PB377
Move.L GrafVars(A0),A0 ; get the data handle
Move.L (A0),A0 ; dereference it
Move.L PmFgColor(A0),A2 ; get the palette handle (finally)
Move.L A2,D0 ; CmpA.L #Nil,A2; is there a palette? AWC.PB508
Bne.S FoundAPltt ; yes => we're cool so far AWC.PB508
Move.L AppPalette,A2 ; grab the AppPalette for use AWC.PB508
Move.L A2,D0 ; CmpA.L #Nil,A2; is there an AppPalette AWC.PB508
Beq GoHome ; no => punt AWC.PB508
FoundAPltt Move.L A2,srcPalette(A6) ; save it so we can unlock it AWC.PB520
Move.L A2,A0 ; put the handle into A0 AWC.PB520
_HLock ; lock it down AWC.PB520
Move.L (A2),A2 ; dereference myPalette AWC.PB508
MoveQ #0,D0 ; clear the high word
Move srcEntry(A6),D0 ; capture the index
Cmp pmEntries(A2),D0 ; D0 - pmEntries; is myEntry out of range?
Bhs UnlockPltt ; yes, so we quit AWC.PB520
Asl.L #4,D0 ; multiply by record size of 16
Lea pmInfo(A2,D0.L),A3 ; set A3 to entry's ColorInfo
CLR.L -(SP) ; Make room for result <dvb7>
Pea ciRGB(A3) ; push address of ciRGB field
BTST #animatedBit,ciUsage+1(A3) ; an animated entry? <dvb11>
BEQ.S @notAn ; No=>plain color2Index <dvb11>
ADDQ.L #1,(SP) ; Yes => use RGB from lo-bytes of ciRGB <dvb11>
@notAn _Color2Index ; Get that index <dvb7>
MOVE.L (SP)+,result(A6) ; Use that, if nothing else goes well. <dvb7>
CLR QDErr ; Well, we got something. <dvb7>
Move.L theGDevice,A0 ; get theGDevice
Move.L (A0),A0 ; dereference it
MOVE.L gdPMap(A0),A1 ; A1 = Pixmap H
MOVE.L (A1),A1 ; A1 -> pixmap
CMPI #2,pixelSize(A1) ; 1 or two bits deep?
BGT.S @b ; No=>don't check pmWhite/Black
MOVE ciUsage(A3),D1 ; D1 = usage
BTST #whiteBit,D1 ; go White on 1-2 bits?
BEQ.S @notWhite ; No=>try black
CLR D0 ; Yes=>result color is white.
BRA.S ShoveIndex
@notWhite BTST #blackBit,D1 ; go Black on 1-2 bits?
BEQ.S @a ; No=>check for animated/explicit stuff
MOVEQ #-1,D0 ; Yes=>Set all the bits for the index
BRA.S inRange ; and trim it to max allowed.
@b
MOVE gdType(A0),D1 ; get the type <dvb12>
BEQ.s @a ; is it a clut device? <dvb12>
SUBQ #1,D1 ; fixed type? <dvb12>
BNE.S UnlockPltt ; no => we're almost done <dvb3>
@a TST gdFlags(A0) ; is it active?
BPL.S UnlockPltt ; no => ditto
Move ciUsage(A3),D1 ; get flags
MoveQ #0,D0 ; clear high word
Move srcEntry(A6),D0 ; set D0 in case it is an explicit index
BTst #AnimatedBit,D1 ; no => test animation bit
Beq.S checkExplct ; if not, maybe explicit AWC.PB520
Jsr FindIndex ; uses our registers - put reserved index in D0
Tst D0 ; was the result "white"?
Beq.S UnlockPltt ; yes => give up
Bra.S ShoveIndex ; share common code
checkExplct BTST #ExplicitBit,D1 ; <dvb4>
BEQ.S UnlockPltt ; <dvb4>
BTST #TolerantBit,D1 ; If we're explicit+tolerant, go with Color2Index.
BNE.S UnlockPltt ; After all, ActivatePal… tried to get it for us.
inRange
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),A0 ; get handle to CTab
Move.L (A0),A0 ; dereference color table
And ctSize(A0),D0 ; and D0 with maximum index
ShoveIndex Move.L D0,result(A6) ; jam the index AWC.PB377
UnlockPltt Move.L SrcPalette(A6),A0 ; get whichever palette we used AWC.PB520
_HUnlock ; unlock it AWC.PB520
GoHome MoveM.L (SP)+,A2-A3 ; restore register
Unlk A6 ; clear stack frame
Rtd #result-return-4 ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE Index2Entries(srcIndex: LONGINT; results:HANDLE):LONGINT;
;
; resize the handle, and return it filled with a list of INTEGERs. The first
; integer is the count, and the rest are the entries in the current port's
; palette that would match to the specified index.
Index2Entries PROC EXPORT
IEVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result: none
srcIndex DS.B 2 ;Input: entry in palette of current port
results DS.B 4 ;Input: any old handle
return DS.B 4
A6Link DS.B 4 ; old contents of A6
linkSize DS.B 0 ; linky number
ENDR
WITH IEVars
LINK A6,#linkSize
MOVEM.L D3-D7/A2,-(SP)
Move.L GrafGlobals(A5),A0 ; get the QuickDraw globals pointer
Move.L ThePort(A0),D0 ; point at the port
BEQ.S @goHome ; No port set?
SUBQ #4,SP
MOVE.L D0,-(SP)
_GetPalette ; Get the current palette
MOVE.L (SP)+,D0 ; Get something?
BEQ.S @goHome
MOVE.L D0,A0
MOVE.L (A0),A0
MOVE pmEntries(A0),D4 ; D4 = number of entries in palette
MOVE.L results(A6),D0 ; Get handle to return stuff in
BEQ.S @goHome ; A problem, to be sure.
MOVEA.L D0,A0
_HGetState
MOVE.B D0,D3 ; D3 = previous state of their handle
_HNoPurge
_HUnlock
MOVE D4,D0 ; D0 = number of entries in palette
ADD D0,D0 ; D0 = twice number of palette entries
ADDQ #2,D0
EXT.L D0 ; D0 = the biggest handle we'd need
_SetHandleSize ; Now, A0 is the right sized handle
_HLock
MOVE.L (A0),A2 ; A2-> where everything will go.
CLR.L D5 ; D5 = number of entries we've found
MOVE.L srcIndex(A6),D6 ; D6 = index we're looking for
BRA.S @scanEnd
@scanLoop SUBQ #4,SP ; Space for long result index
MOVE D4,-(SP)
_Entry2Index
CMP.L (SP)+,D6 ; Does this entry match our index?
BNE.S @scanEnd
ADDQ #1,D5 ; Found one more...
MOVE D4,(A2,D5*2) ; Put the entry into the list o' entries
@scanEnd DBRA D4,@scanLoop
MOVE.L results(A6),A0
MOVE.L D5,D0
ADD.L D0,D0
ADDQ.L #2,D0
_SetHandleSize
MOVE.B D3,D0
_HSetState
@goHome MOVEM.L (SP)+,D3-D6/A2
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
; PROCEDURE PmForeColor(srcEntry: INTEGER); INLINE $AA97;
;
PmForeColor PROC EXPORT
EXPORT PmBackColor
PCVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result: none
srcEntry DS.B 2 ;Input: entry in palette of current port
return DS.B 4
A6Link DS.B 4 ; old contents of A6
callType DS.B 2 ; Fore- or Back- call
linkSize DS.B 0 ; linky number
ENDR
WITH PCVars
;PmForeColor
MoveQ #1,D0 ; we're coming from PmForeColor
Bra.S PmSetColor ; share code
PmBackColor MoveQ #0,D0 ; we're coming from PmBackColor
PmSetColor Link A6,#linkSize ; build stack frame
Move D0,callType(A6) ; save the type of call
CLR.L -(SP) ; Room for result
MOVE srcEntry(A6),-(SP) ; Push the entry input
_Entry2Index ; Find a good index for it
MOVE.L (SP)+,D0 ; Get index (if any) into D0
TST QDErr ; Found one?
BNE.S GoHome ; No, skip it.
Move.L GrafGlobals(A5),A0 ; get the QuickDraw globals pointer
Move.L ThePort(A0),A0 ; point at the port
MOVE.L GrafVars(A0),A1 ; A1 = Grafvars handle
MOVE.L (A1),A1 ; A1->Grafvars
MOVE.L D0,-(SP) ; Push index for Index2Color <dvb9>
Tst callType(A6) ; foreground? AWC.PB377
Beq.S SetBackgrnd ; no => set background AWC.PB377
Move.L D0,FgColor(A0) ; jam the index
Move srcEntry(A6),PmFgIndex(A1) ; save the entry number
BSet #PmFgBit,PmFlags+1(A1) ; tell the world that we set the FgColor
PEA rgbFgColor(A0) ; Push address of color result o' Index2Color <dvb9>
Bra.S ToColor ; continue AWC.PB377
SetBackgrnd Move.L D0,BkColor(A0) ; jam the index AWC.PB377
Move srcEntry(A6),PmBkIndex(A1) ; save the entry number
BSet #PmBkBit,PmFlags+1(A1) ; tell the world that we set the BkColor
PEA rgbBkColor(A0) ; Push address of color result o' Index2Color <dvb9>
ToColor _Index2Color ; Give port rgb color from index result <dvb9>
GoHome Unlk A6 ; clear stack frame
Rtd #result-return-4 ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE AnimateEntry(dstWindow: WindowPtr; dstEntry: INTEGER; srcRGB: RGBColor); INLINE $AA99;
;
AnimateEntry PROC EXPORT
ParamSize equ 10 ; total bytes of params <AWC>
dstWindow equ ParamSize+8-4 ; target window <AWC>
dstEntry equ dstWindow-2 ; palette entry to animate <AWC>
srcRGB equ dstEntry-4 ; new color to use
SaveGDevice equ -4 ; room for saving theGDevice
Mc equ SaveGDevice-6 ; RGBColor
OldSeed equ Mc-4 ; old color table seed
VarSize equ OldSeed ; size of the variables
Link A6,#VarSize ; build stack frame
MoveM.L D3-D5/A2-A4,-(SP) ; save registers
Move.L PMgrHandle,A3 ; get the main handle
CmpA.L #PMgrNil,A3 ; are we initialized?
Beq GoHome ; no => punt AWC.PB377
Move.L dstWindow(A6),A0 ; get the target window
CmpA.L #Nil,A0 ; is it nil?
Beq GoHome ; yes => we're done AWC.PB377
Tst PortBits+Rowbytes(A0) ; is it a new port?
Bpl GoHome ; no => punt AWC.PB377
Move.L GrafVars(A0),A0 ; get the data handle
Move.L (A0),A0 ; dereference it
Move.L PmFgColor(A0),A2 ; get the palette handle (finally)
Move.L A2,D0 ; CmpA.L #Nil,A2; is there a palette? AWC.PB508
Bne.S FoundAPltt ; yes => use it AWC.PB508
Move.L AppPalette,A2 ; look for an AppPalette AWC.PB508
Move.L A2,D0 ; CmpA.L #Nil,A2; is there an AppPalette? AWC.PB508
Beq GoHome ; no => punt AWC.PB377
FoundAPltt Move.L (A2),A0 ; dereference the palette AWC.PB508
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move dstEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs GoHome ; no => we're done AWC.PB377
Lsl #4,D1 ; multiply by ciSize
Lea pmInfo(A0,D1.L),A2 ; point A2 at the entry
; BTst #ExplicitBit,ciUsage+1(A2) ; is it explicit? <dvb4>
; Bne GoHome ; yes => by definition not animating <dvb4>
BTst #AnimatedBit,ciUsage+1(A2) ; is it animating?
Beq GoHome ; no => quit
; Copy the colors to the palette before we check to see if we have links or not so that it
; will get copied even if we have no 'clut' devices
Move.L srcRGB(A6),A0 ; get pointer to his RGB AWC.PB500
Move.L red(A0),D0 ; copy red and green AWC.PB500
Move.L D0,mc+red(A6) ; save red and green on the stack AWC.PB500
ROR.L #8,D0 ; Get at upper bytes of colors <dvb6>
MOVE.b d0,ciRGB+green(A2) ; Only store high byte (lo is SetColor <dvb11>
SWAP D0 ; get at red byte <dvb6>
MOVE.B D0,ciRGB+red(A2) ; Only store high byte (lo is SetColor <dvb11>
Move blue(A0),D0 ; copy blue AWC.PB500
Move D0,mc+blue(A6) ; save blue on the stack AWC.PB500
ROR #8,D0 ; get at significant byte of blue <dvb6>
MOVE.B D0,ciRGB+blue(A2) ; Only store high byte (lo is SetColor <dvb11>
Move ciPrivate(A2),D3 ; get the ForeLink field
BfExtu D3{16:3},D1 ; get the key bits
Cmp #4,D1 ; were they 100?
Bne GoHome ; no => not a valid ForeLink; go home
; Now, finally, we have something to do. Let's follow those links and see where they take us
Move.L A3,A0 ; copy PMgrHandle
_HLock ; lock it down
Move.L theGDevice,SaveGDevice(A6) ; save it
; Register usage:
;
; D0 : holds ForeLink temporarily
; D3 : holds device number
; D4 : holds index number
; D5 : watchdog loop counter
;
; A2 : base address of LinkTabs
; A3 : PMgrHandle (locked)
; A4 : base address of DevHandles
Move.L (A3),A2 ; dereference PMgrHandle
Move nDevs(A2),D5 ; maximum number of devices (watchdog counter)
Lea DevHandles(A2),A4 ; point A4 at the device list
AddA.L #LinkTabs,A2 ; point A2 at start of LinkTabs
Move D3,D0 ; copy ForeLink into D0
Bra.S DevEnd ; jump into the loop
DevLoop BfExtU D0{19:5},D3 ; grab device number (0..31)
BfExtU D0{24:8},D4 ; grab index number (0..255)
Move.L DevHandle(A4,D3.W*8),A0 ; get the device handle
Move.L A0,theGDevice ; now we're on that device
Move.L (A0),A0 ; dereference it
Clr gdId(A0) ; no client id's, please
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),A0 ; get handle to CTab
Move.L (A0),A0 ; dereference CTab
Move ctSize(A0),D0 ; grab number of entries - 1
Cmp D4,D0 ; compare our index to the max index
Ble.S NextDevice ; out of range => look at next device AWC.PB480
Move.L ctSeed(A0),OldSeed(A6) ; save the seed so we can restore it
Move.L mc+red(A6),ctTable+RGB+red(A0,D4.W*8)
Move mc+blue(A6),ctTable+RGB+blue(A0,D4.W*8)
; Now perform a sequential _SetEntries using the device's color table as the source
MOVE D4,-(SP) ; push D4 = Index for SetEntries
CLR -(SP) ; push number of entries-1 = 1
Pea ctTable(A0,D4*8) ; push address of the first ColorSpec
_SetEntries ; do it
Move.L theGDevice,A0 ; get the device again
Move.L (A0),A0 ; dereference it
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),A0 ; get handle to CTab
Move.L (A0),A0 ; dereference CTab
Move.L OldSeed(A6),ctSeed(A0) ; we didn't really want it to change
NextDevice Lsl #8,D3 ; calculate offset to link table/4
Add D4,D3 ; offset to entry/4
Move ForeLink(A2,D3.L*4),D0 ; get next link; is the top bit set? AWC.PB500
DevEnd DBpl D5,DevLoop ; keep going until D0 is positive or D5 runs out
Move.L SaveGDevice(A6),theGDevice ; restore theGDevice
Move.L A3,A0 ; copy PMgrHandle
_HUnlock ; unlock it
GoHome MoveQ #0,D0 ; no error AWC.PB377
MoveM.L (SP)+,D3-D5/A2-A4 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE AnimatePalette(dstWindow:WindowPtr; srcCTab: CTabHandle; srcIndex,
; dstEntry,dstLength: INTEGER; INLINE $AA9A;
;
AnimatePalette PROC EXPORT
ParamSize equ 14 ; total bytes of params <AWC>
dstWindow equ ParamSize+8-4 ; window to animate <AWC>
srcCTab equ dstWindow-4 ; new source colors
srcIndex equ srcCTab-2 ; first source entry to use
dstEntry equ srcIndex-2 ; first destination entry to set
dstLength equ dstEntry-2 ; how many to set
SaveGDevice equ -4 ; room for saving theGDevice
SaveSeed equ SaveGDevice-4 ; old color table seed
NumDev equ SaveSeed-2 ; copy of nDevs
DevCTabH equ NumDev-DevLimit*4 ; enough room for a CTabHandle per device
VarSize equ DevCTabH ; size of the variables
Link A6,#VarSize ; build stack frame
MoveM.L D3-D6/A2-A4,-(SP) ; save registers
Move.L PMgrHandle,A4 ; get the main handle
CmpA.L #PMgrNil,A4 ; are we initialized?
Beq GoHome ; no => punt AWC.PB377
Move.L dstWindow(A6),A0 ; get the target window <AWC>
CmpA.L #Nil,A0 ; is it nil? <AWC>
Beq GoHome ; yes => we're done AWC.PB377
Tst PortBits+Rowbytes(A0) ; is it a new port?
Bpl GoHome ; no => punt AWC.PB377
Move.L GrafVars(A0),A0 ; get the data handle
Move.L (A0),A0 ; dereference it
Move.L PmFgColor(A0),A2 ; get the palette handle (finally)
Move.L A2,D0 ; CmpA.L #Nil,A2; is there a palette? AWC.PB508
Bne.S FoundAPltt ; yes => use it AWC.PB508
Move.L AppPalette,A2 ; look for an AppPalette AWC.PB508
Move.L A2,D0 ; CmpA.L #Nil,A2; is there an AppPalette? AWC.PB508
Beq GoHome ; no => punt AWC.PB508
FoundAPltt Move.L srcCTab(A6),A3 ; get source color table AWC.PB508
Move.L A3,D0 ; CmpA.L #Nil,A3; is it nil? AWC.PB508
Beq GoHome ; yes => again punt AWC.PB377
Move.L (A2),A2 ; dereference the palette
Move pmEntries(A2),D0 ; get the number of entries; are there any?
Beq GoHome ; no => still punt AWC.PB377
MoveQ #0,D3 ; clear high word (so we can Lsl.L later)
Move dstEntry(A6),D3 ; get the starting index
Cmp D0,D3 ; is the start after the end?
Bhs GoHome ; yes => keep punting
Move.L (A3),A3 ; dereference the color table
Move srcIndex(A6),D4 ; get the starting index
Cmp ctSize(A3),D4 ; is the starting index within range?
Bhi GoHome ; no => once more, punt
; We have something worth copying! Now we can determine the length of the copy and
; place it in D5.
Sub D3,D0 ; calculate maximum length of a palette copy
Move D0,D5 ; save it in D5
Move ctSize(A3),D0 ; fetch the length of the color table
AddQ #1,D0 ; add 1 to make it 1-based
Sub D4,D0 ; calculate maximum length of a CTab copy
Cmp D0,D5 ; is D5 too big?
Bls.S NotTooBig ; no => don't replace it
Move D0,D5 ; copy smaller value to D5
NotTooBig Cmp dstLength(A6),D5 ; is D5 bigger than the request?
Bls.S StillOkay ; no => leave it alone
Move dstLength(A6),D5 ; copy smaller value to D5
StillOkay Move.L (A4),A1 ; dereference the palette manager handle
Move nDevs(A1),D0 ; put number of devices into D0
Move D0,NumDev(A6) ; remember number of devices
Lea DevHandles(A1),A4 ; point A4 at the clut device list AWC
Lea DevCTabH(A6),A0 ; point A0 at our temporary table AWC
Bra.S ClearEnd ; jump into loop
ClearLoop Clr.L (A0)+ ; clear room for a handle AWC
ClearEnd DBra D0,ClearLoop ; continue for nDevs devices AWC
AddA.L #LinkTabs,A1 ; bump A1 to the link tables
Lsl.L #4,D3 ; multiply D3 by ciSize
Lea pmInfo(A2,D3.L),A2 ; bump A2 to first ColorInfo
Lea ctTable(A3,D4.W*8),A3 ; bump A3 to first ColorSpec
Bra EntryEnd ; jump into loop
EntryLoop BTst #AnimatedBit,ciUsage+1(A2) ; is it animating?
Beq NextEntry ; no => continue
MOVE.b RGB+red(A3),ciRGB+red(A2) ; red hi into our hibyte <dvb11>
MOVE.b RGB+green(A3),ciRGB+green(A2) ; green hi into our hibyte <dvb11>
MOVE.b RGB+blue(A3),ciRGB+blue(A2) ; blue hi into our hibyte <dvb11>
Move ciPrivate(A2),D0 ; get the ForeLink field
BfExtu D0{16:3},D1 ; get the key bits
Cmp #4,D1 ; were they 100?
Bne.S NextEntry ; no => not a valid ForeLink; go home
Move NumDev(A6),D6 ; get maximum number of devices to examine
SubQ #1,D6 ; decrement by 1 so we may fall through
; We fall through because the usual trick of branching to the end won't work when the
; end is a DBpl, not a DBf (DBra).
DevLoop BfExtU D0{19:5},D3 ; grab device number (0..31)
BfExtU D0{24:8},D4 ; grab index number (0..255)
Lea DevCTabH(A6),A0 ; point A0 at temporary table
Move.L (A0,D3.W*4),A0 ; get CTabHandle
CmpA.L #Nil,A0 ; have we seen this device yet?
Bne.S SeenDevice ; yes => skip setup
Move.L DevHandle(A4,D3.W*8),A0 ; get the device handle
Move.L (A0),A0 ; dereference it
Clr gdId(A0) ; no client id's, please
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),D0 ; get handle to CTab
Lea DevCTabH(A6),A0 ; point A0 at temporary table
Move.L D0,(A0,D3.W*4) ; save it for later
Move.L D0,A0 ; copy CTabHandle back into A0 AWC PB223
SeenDevice Move.L (A0),A0 ; dereference CTab
Move ctSize(A0),D0 ; grab number of entries - 1
Cmp D4,D0 ; compare our index to the max index
Ble.S NextDevice ; out of range => look at next device AWC.PB480
Move.W ciRGB+red(A2),ctTable+RGB+red(A0,D4.W*8) ;<dvb11>
Move.W ciRGB+green(A2),ctTable+RGB+green(A0,D4.W*8) ;<dvb11>
Move.W ciRGB+blue(A2),ctTable+RGB+blue(A0,D4.W*8) ;<dvb11>
NextDevice Lsl #8,D3 ; calculate offset to link table/4
Add D4,D3 ; offset to entry/4
Move ForeLink(A1,D3.L*4),D0 ; get next link; is the top bit set?
DevEnd DBpl D6,DevLoop ; keep going until D0 is positive or D5 runs out
NextEntry AddA.L #ciSize,A2 ; bump A2 to next ColorInfo
AddA.L #ColorSpecSize,A3 ; bump A3 to next ColorSpec
EntryEnd DBra D5,EntryLoop ; continue for all animating entries
Move.L theGDevice,SaveGDevice(A6) ; save the old GDevice
Move NumDev(A6),D6 ; get number of devices to examine
Lea DevCTabH(A6),A2 ; point A2 at our temporary table
Bra.S SetEnd ; jump into loop
SetLoop Move.L (A2)+,A3 ; get next CTabHandle
CmpA.L #Nil,A3 ; did we initialize it?
Beq.S NextSet ; no => continue
Move.L DevHandle(A4),theGDevice ; put us on that device
Move.L (A3),A0 ; dereference it
Move.L ctSeed(A0),SaveSeed(A6) ; save the current seed
Clr -(SP) ; push starting count of 0 for SetEntries
Move ctSize(A0),-(SP) ; push number of entries-1
Pea ctTable(A0) ; push address of the first ColorSpec
_SetEntries ; do it
Move.L (A3),A0 ; dereference CTab again
Move.L SaveSeed(A6),ctSeed(A0) ; put the old seed back into place
NextSet AddQ.L #DevInfoSz,A4 ; bump A4 to the next device
SetEnd DBra D6,SetLoop ; loop for all devices
Move.L SaveGDevice(A6),theGDevice ; restore the old GDevice
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
MoveM.L (SP)+,D3-D6/A2-A4 ; rsstore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE GetEntryColor(srcPalette: PaletteHandle; srcEntry: INTEGER; VAR dstRGB: RGBColor);
; INLINE $AA9B;
;
GetEntryColor PROC EXPORT
ParamSize equ 10 ; total bytes of params
srcPalette equ ParamSize+8-4 ; source Palette handle
srcEntry equ srcPalette-2 ; entry to get
dstRGB equ srcEntry-4 ; where to put color
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L srcPalette(A6),A0 ; get palette
CmpA.L #Nil,A0 ; is it nil?
Beq.S GoHome ; yes => punt AWC.PB377
Move.L (A0),A0 ; dereference it
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move srcEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs.S GoHome ; no => we're done AWC.PB377
Lsl.L #4,D1 ; multiply by number of records
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
Move.L dstRGB(A6),A1 ; get the destination
Move.L ciRGB+red(A0),red(A1) ; copy red and green
Move ciRGB+blue(A0),blue(A1) ; copy blue
GoHome MoveQ #0,D0 ; clear error condition
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE ScatterDevices(SetEm:Boolean); Local; <dvb3>
;
; Here is the long awaited ScatterDevices, which gives animated entries back to
; the world in a socially acceptable manner. The default clut for the device
; is used to fill in those entries of the device's clut marked with bit 4,
; the ctScatterBit. Then, the bits for those devices with new colors is set in
; the updateDevs bitmask of PMgrHandle.
; We restore all registers.
ScatterDevices PROC EXPORT
SDVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result: none
SetEm DS.B 2 ;Input: boolean, to set the entries really
return DS.B 4
A6Link DS.B 4 ;old contents of A6
linkSize DS.B 0 ;linky number
ENDR
WITH SDVars
LINK A6,#linkSize
MOVEM.L A0/A2-A4/D1-D5,-(SP) ; Save some regs
MOVE.L PMgrHandle,A0
MOVE.L (A0),A0 ; A0 -> PMgr data
MOVE.L scatterDevs(A0),D4 ; D4 = bitmask of devices needing scattering
BEQ GoHome ; What? No scattering?
CLR.L scatterDevs(A0) ; We'll scatter these
OR.L D4,updateDevs(A0) ; So mark them for updating
MOVE nDevs(A0),D3 ; D3 = number of devices to check
SUBQ #1,D3 ; less one (we've got _one_ device, right?)
LEA DevHandles(A0),A2 ; A2 -> list of devices
ScatterLoop BTST D3,D4 ; Do this device?
BEQ ScatterEnd ; No=> skip some stuff
SUBQ #4,SP ; space for result
MOVE.L DevHandle(A2,D3*8),A3 ; A3 = device handle
MOVE.L A3,-(SP) ; push device handle
JSR GetClut ; get us a handle
MOVE.L (SP)+,A4 ; Keep copy on stack
MOVE.L (A4),A4 ; A4-> system color table for that depth
MOVE.L ctSeed(A4),D2 ; D2 = system seed for that depth
LEA ctTable+rgb(A4),A4 ; A4-> rgb of first color entry
MOVE.L (A3),A3 ; A3->gDevice
MOVE.L gdPMap(A3),A3 ; A3 = pixmaphandle
MOVE.L (A3),A3 ; A3->pixmap
MOVE.L pmTable(A3),A3 ; A3 = our color table H
MOVE.L (A3),A3 ; A3-> our color table
MOVE ctSize(A3),D1
LEA ctTable(A3),A0 ; A0->value of colorspec 0
CLR D5 ; No elements scattered
EntryLoop BTST #ctMatchBit,value(A0) ; Is this entry looked at?
BEQ.S CheckScat ; No=>check next one
ADDQ #1,D5 ; Count number of unreserved entries
CheckScat BTST #ctScatterBit,value(A0) ; Is the scatterbit on?
BEQ.S EntryEnd ; No=>check next one
CLR value(A0) ; Mark it as unreserved, scattered, etc.
MOVE.L red(A4),rgb+red(A0) ; Move red and green component from system clut
MOVE blue(A4),rgb+blue(A0) ; Move blue from system clut
EntryEnd ADDQ #8,A0 ; Bump A0 to next color entry
ADDQ #8,A4 ; Bump A4 to next color entry
DBRA D1,EntryLoop
MOVE.L DevHandle(A2,D3*8),A4 ; A4 = device handle
CMP ctSize(A3),D5 ; Is every entry in place as in default?
BLE.S NewSeed ; No=>give cTab a new seed
MOVE.L D2,ctSeed(A3) ; Yes=>we get system seed here
MOVE.L (A4),A0 ; A0->gDevice
MOVE.L gdITable(A0),A0 ; A0 = Inverse table handle
MOVE.L (A0),A0 ; A0-> ITable
CLR.L (A0) ; Change ITab seed instead!
BRA.S MaybeSet
NewSeed SUBQ #4,SP ; Space for result
_GetCTSeed ; Get us a new seed
MOVE.L (SP)+,ctSeed(A3) ; And give it a new seed.
MaybeSet TST SetEm(A6) ; So, do we actually update the device?
BEQ.S ScatterEnd ; No=>do next device
MOVE.L A4,A0 ; Put gDev handle in A0
JSR DevSetEntries ; And put entries into HW clut, w/o changing seed.
ScatterEnd DBRA D3,ScatterLoop
GoHome MOVEM.L (SP)+,A0/A2-A4/D1-D5
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
; PROCEDURE SetDev; LOCAL;
;
; Renders or allocates myPalette as appropriate for the given device. If myPalette
; is polite it accumulates reference counts. If it is intolerant it assigns indexes
; according to closest match and makes these colors available in the color table. If
; it is adamant (animated) it chooses indexes according to lowest reference counts
; and reserves the entries on the device (setting the reserve bit).
;
; This function uses the stack frame built upon A6 and builds its own stack frame on A4.
PROC
EXPORT SetDev
OldPort equ -8 ; a place to stuff the port while we InvalRect
SysUpdates equ OldPort-2 ; flag that tells whether the system wants updates
OldUpdates equ SysUpdates-2 ; flag => 1 if Old Quickdraw colors got changed AWC
VarSize equ OldUpdates ; number of bytes of variables AWC PB223
DepthBits DC.B 8,9,10,11,0,0,12,13 ; Inhibit bits for different depths/grays
; (depth) 2 2 4 4 8 8
; (color?) n y n y n y
SetDev
Link A4,#VarSize ; build stack frame
MoveM.L D3-D5/A2-A3,-(SP) ; save registers <AWC>
; Grab the device handle and shove it into theGDevice
Move CurDevice(A6),D3 ; get device offset
Move.L PDevPtr(A6),A0 ; get pointer to internal list of devices
Move.L (A0,D3.W*8),A0 ; get the device handle
Move.L A0,theGDevice ; set theGDevice
; Removed code that calculated device info - see CalcDevs below AWC PB223
Move.L (A0),A0 ; dereference it
TST gdType(A0) ; is it CLUT type (zero)? dvb1
BNE GoHome ; No => do nothing
TST gdFlags(A0) ; is it active
BPL GoHome ; No=>go home
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),A0 ; get handle to CTab
Move.L A0,DevCTab(A6) ; save color table handle, too
Move.L (A0),A0 ; dereference CTab
Move ctSize(A0),D0 ; grab number of entries - 1
Move D0,BlackIndex(A6) ; save it
AddQ #1,D0 ; bump it to number of entries
Move D0,DevIndexes(A6) ; save the number of indexes, too
; Compare the palette's seed for this device to the ctSeed belonging to the
; device. If they match, no environment or palette change has occurred. The routines
; which modify palettes make sure that the appropriate seed fields get changed. If
; the user modifies the palette herself, she must take responsibility for changing
; the seeds accordingly.
Move.L ctSeed(A0),D0 ; read the current device seed
Move.L PalettePtr(A6),A0 ; get the Palette pointer
BTst #DirtyBit,pmPrivate(A0) ; does it need an update anyway?
Bne.S DirtyBird ; yes => activate it anyway
Move.L pmSeeds(A0),A0 ; get the handle to the seeds
Move.L (A0),A0 ; dereference it
Cmp.L (A0,D3.W*4),D0 ; does the Palette's seed match the device's?
Beq GoHome ; yes => skip this whole mess
; Set up some useful pointers
DirtyBird Move.L PDevPtr(A6),A0 ; get pointer to internal list of devices
Lea (A0,D3.W*8),A0 ; point A0 at the device entry
Move.L PMgrPtr(A6),A0 ; copy base pointer
AddA.L #LinkTabs,A0 ; add offset to first link table
Move D3,D0 ; get the device number (0..31)
Lsl #8,D0 ; multiply by link table size (max 31*1024)
Lea (A0,D0.W*4),A0 ; point A0 at link table
Move.L A0,DevLinks(A6) ; save pointer to device links table
; Set Updates to 0 so we'll know if a SetEntries is necessary. Make a copy
; of ciUsage flags in ciFlags.
Clr Updates(A6) ; clear number of updates to CTab we've done
MOVE.L TheGDevice,A0 ; A0 = Current device handle
MOVE.L (A0),A0 ; A0->Current device
MOVE gdFlags(A0),D3 ; D3 = gDev's flags
AND #1,D3 ; D3 = 0:b/w or 1:color
MOVE.L gdPMap(A0),A0 ; A0 = current device pixmap
MOVE.L (A0),A0 ; A0->current device pixmap
ADD pmPixelSize(A0),D3 ; D3 = pixeldepth, +1 if color
LEA depthBits-2,A0
MOVE.B (A0,D3.W),D3 ; D3 = bit of ciUsage to test for inhibit on this gDev
Move myEntries(A6),D0 ; get myPalette^^.pmEntries
Move.L PalettePtr(A6),A0 ; get the pointer to the palette
Lea pmInfo(A0),A0 ; bump it to the first ColorInfo
Bra.S InitEnd ; jump into the fray
InitLoop Move ciUsage(A0),D1 ; D1 = usage flags, plus global HandledBit
BTST D3,D1 ; Inhibit on this device?
BEQ.S @noInhib
BSET #handledBit,D1 ; Yes, just mark as "handled"
@noInhib MOVE D1,ciFlags(A0) ; copy ciUsage to ciFlags
AddA.L #ciSize,A0 ; bump A0 to the next ColorInfo
InitEnd DBra D0,InitLoop ; loop for pmEntries
JSR AnalyzeDev ; Make list of device indices to grab
Jsr PMAllocate ; Get animated entries
Jsr Correlate ; Get tolerant entries
; Now we are ready to set some colors (for real, man!). We have been changing colors
; in the device's color table all along. Now we just need to promulgate them through
; to the device with a sequential SetEntries call, but only if Updates is greater than
; zero. In order to make the call we have to unprotect each color and set it's client
; id to "none". Then we do the SetEntries call, after which we restore the protection
; and client id (255) of all colors. Next we copy the seed from the device color table
; to the palette so we'll know we've been here. Finally we generate update events for
; all windows of palettes which have been rendered on this device, including of course
; the current palette.
CheckUpdate TST Updates(A6)
BEQ.S FixSeeds
JSR MarkDevUBit
FixSeeds Move.L DevCTab(A6),A0 ; get color table
Move.L (A0),A0 ; dereference it
Move.L ctSeed(A0),D0 ; read the current device seed
Move.L PalettePtr(A6),A0 ; get the Palette pointer
Move.L pmSeeds(A0),A1 ; get the handle to the seeds
Move.L (A1),A1 ; dereference it
Move CurDevice(A6),D3 ; get device number back
Move.L D0,(A1,D3.W*4) ; update the Palette's seed
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
MoveM.L (SP)+,D3-D5/A2-A3 ; restore registers <AWC>
Unlk A4 ; clear stack frame
Rts ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE SetEntryColor(dstPalette: PaletteHandle; dstEntry: INTEGER; srcRGB: RGBColor);
; INLINE $AA9C;
;
SetEntryColor PROC EXPORT
ParamSize equ 10 ; total bytes of params
dstPalette equ ParamSize+8-4 ; source Palette handle
dstEntry equ dstPalette-2 ; entry to set
srcRGB equ dstEntry-4 ; new color
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L dstPalette(A6),A0 ; get palette
CmpA.L #Nil,A0 ; is it nil?
Beq.S GoHome ; yes => punt AWC.PB377
Move.L (A0),A0 ; dereference it
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move dstEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs.S GoHome ; no => we're done AWC.PB377
Lsl.L #4,D1 ; multiply by number of records
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
Move.L srcRGB(A6),A1 ; A1->source
Move.L red(A1),ciRGB+red(A0) ; copy red and green,
Move blue(A1),ciRGB+blue(A0) ; copy blue
BTST #animatedBit,ciUsage+1(A0) ; Is it animated? <dvb13>
BEQ.S @notAni ; No=> don't replicate bytes <dvb13>
LEA ciRGB(A0),A0 ; (A nop, I think)
MOVE.B (A0)+,(A0)+ ; we replicate the high bytes
MOVE.B (A0)+,(A0)+ ; of each component into the low bytes
MOVE.B (A0)+,(A0)+
@notAni Move.L dstPalette(A6),-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE GetEntryUsage(srcPalette: PaletteHandle; srcEntry: INTEGER; VAR dstUsage,
; dstTolerance: INTEGER); INLINE $AA9D;
;
GetEntryUsage PROC EXPORT
ParamSize equ 14 ; total bytes of params
srcPalette equ ParamSize+8-4 ; source Palette handle
srcEntry equ srcPalette-2 ; entry number
dstUsage equ srcEntry-4 ; where to put usage
dstTolerance equ dstUsage-4 ; where to put tolerance
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L srcPalette(A6),A0 ; get palette
CmpA.L #Nil,A0 ; is it nil?
Beq.S GoHome ; yes => punt AWC.PB377
Move.L (A0),A0 ; dereference it
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move srcEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs.S GoHome ; no => we're done AWC.PB377
Lsl.L #4,D1 ; multiply by number of records
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
Move.L dstUsage(A6),A1 ; get the destination
Move ciUsage(A0),(A1) ; copy usage
Move.L dstTolerance(A6),A1 ; get the second destination
Move ciTolerance(A0),(A1) ; copy tolerance
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE SetEntryUsage(dstPalette: PaletteHandle; dstEntry,srcUsage,srcTolerance: INTEGER);
; INLINE $AA9E;
;
SetEntryUsage PROC EXPORT
IMPORT ClearStrand
ParamSize equ 10 ; total bytes of params
dstPalette equ ParamSize+8-4 ; source Palette handle
dstEntry equ dstPalette-2 ; entry number
srcUsage equ dstEntry-2 ; new usage
srcTolerance equ srcUsage-2 ; new tolerance
VarSize equ 0
Link A6,#VarSize ; build stack frame
MOVEM.L A2-A4/D3-D4,-(SP) ; save regs <dvb3>
Move.L dstPalette(A6),A0 ; get palette
CmpA.L #Nil,A0 ; is it nil?
Beq.S GoHome ; yes => punt AWC.PB377
Move.L (A0),A0 ; dereference it
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move dstEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs.S GoHome ; no => we're done AWC.PB377
Lsl.L #4,D1 ; multiply by number of records
Lea pmInfo(A0,D1.L),A2 ; point A2 at the correct ColorInfo
MOVE ciUsage(A2),D0 ; D0 = old usage <dvb3>
BTST #AnimatedBit,D0 ; Was it animated before? <dvb3>
BEQ.S NoScat ; If not, we've nothing to release <dvb3>
MOVE srcUsage(A6),D3
EOR D3,D0 ; And, which bits changed <dvb3>
AND #$3F0C,D0 ; Animated, explicit, OR inhibits? <dvb4>
BEQ.S noScat ; None? No change to fix <dvb4>
MOVE ciPrivate(A2),D3 ; Yes, were any indexes actually reserved? <dvb3>
BPL.S NoScat ; No => still no entries to release <dvb3>
MOVE.L PMgrHandle,A0 ; A0 = pmgr handle <dvb3>
MOVE.L (A0),A0 ; A0 ->pmgr data <dvb3>
LEA LinkTabs(A0),A3 ; A3 -> LinkTabs <dvb3>
LEA DevHandles(A0),A4 ; A4 -> Device handles <dvb3>
CLR.L D4 ; No devices affected... yet <dvb3>
JSR ClearStrand ; clear linktab/ctTable entries <dvb3>
MOVE.L PMgrHandle,A0 ; A0 = pmgr handle <dvb3>
MOVE.L (A0),A0 ; A0 ->pmgr data <dvb3>
OR.L D4,scatterDevs(A0) ; Mark some devices for scattering <dvb3>
CLR ciPrivate(A2) ; We no longer own those indices. <dvb3>
NoScat MOVE srcUsage(A6),D0 ; Get new usage in D0 <dvb14>
BTST #AnimatedBit,D0 ; Will it be now animated? (rgrdlss prior state) <dvb14>
BEQ.S @NoDup ; No => don't dupe high/low bytes <dvb14>
LEA ciRGB(A2),A0 ; A0->rgb color <dvb14>
MOVE.B (A0)+,(A0)+ ; Dupe red into low byte <dvb14>
MOVE.B (A0)+,(A0)+ ; Dupe green into low byte <dvb14>
MOVE.B (A0)+,(A0)+ ; Dupe blue into low byte <dvb14>
@NoDup Move D0,ciUsage(A2) ; copy usage
Move srcTolerance(A6),ciTolerance(A2) ; copy tolerance
Move.L dstPalette(A6),-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
MOVEM.L (SP)+,A2-A4/D3-D4 ; restore regs <dvb3>
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE CTab2Palette(srcCTab: CTabHandle; dstPalette: PaletteHandle; myUsage,
; myTolerance: INTEGER); INLINE $AA9F;
;
CTab2Palette PROC EXPORT
ParamSize equ 12 ; total bytes of params
srcCTab equ ParamSize+8-4 ; source ColorTable handle
dstPalette equ srcCTab-4 ; destination Palette handle
srcUsage equ dstPalette-2 ; default usage value
srcTolerance equ srcUsage-2 ; default usage tolerance
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D3/A2-A3,-(SP) ; save registers
Move.L dstPalette(A6),A2 ; get palette
CmpA.L #Nil,A2 ; is it nil?
Beq GoHome ; can't deal with nil here either AWC.PB377
Move.L dstPalette(A6),-(SP) ; push Palette
Jsr ClearPalette ; clear animating entries and seed handle
Bne.S GoHome ; if not zero it was a bad palette AWC.PB457
Move.L srcCTab(A6),A3 ; get color table
CmpA #Nil,A3 ; is it nil?
Beq.S GoHome ; can't deal with a nil handle AWC.PB377
Move.L (A3),A1 ; dereference it
MoveQ #0,D3 ; clear high word of D3
Move ctSize(A1),D3 ; get size-1 of CTab
AddQ #1,D3 ; D3 is number of entries in palette
Move.L A2,A0 ; copy myPalette handle
Move.L D3,D0 ; copy size
AddQ #1,D0 ; include palette header
Asl #4,D0 ; multiply by 16 bytes per entry | header
_SetHandleSize ; do it
Bne.S GoHome ; and quit if we couldn't do it AWC.PB377
Move.L A2,-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
Move.L (A2),A0 ; dereference our handle
Move D3,pmEntries(A0) ; copy size
AddA.L #pmInfo,A0 ; bump us to the first ColorInfo
Move.L (A3),A1 ; dereference source handle again
AddQ.L #ctTable,A1 ; bump A1 to the first ColorSpec
Move srcUsage(A6),D1 ; grab myUsage from parameters
Swap D1 ; put it in high word
Move srcTolerance(A6),D1 ; grab myTolerance into low word
Bra.S CopyEnd ; jump into DBra loop
CopyLoop Move.L RGB+red(A1),ciRGB+red(A0) ; copy red and green <dvb11>
Move RGB+blue(A1),ciRGB+blue(A0) ; copy blue
BTST #animatedBit+16,D1 ; animated entry? <dvb13>
BEQ.S @notAni ; No=>don't mangle hi/lo bytes <dvb13>
MOVE.B RGB+red(A1),ciRGB+red+1(A0) ; copy red into lo byte
MOVE.B RGB+green(A1),ciRGB+green+1(A0) ; copy green into lo byte <dvb11>
MOVE.B RGB+blue(A1),ciRGB+blue+1(A0) ; copy blue into lo byte <dvb11>
@notAni Move.L D1,ciUsage(A0) ; copy myUsage and myTolerance
Clr ciFlags(A0) ; clear private flags
Clr ciPrivate(A0) ; clear private links
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
CopyEnd DBra D3,CopyLoop ; decrement and branch until copy is done
GoHome MoveQ #0,D0 ; clear error AWC.PB377
MoveM.L (SP)+,D3/A2-A3 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE Palette2CTab(srcPalette: PaletteHandle; dstCTab: CTabHandle); INLINE $AAA0;
;
Palette2CTab PROC EXPORT
ParamSize equ 8 ; total bytes of params
srcPalette equ ParamSize+8-4 ; source Palette handle
dstCTab equ srcPalette-4 ; destination CTabHandle
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D3/A2-A3,-(SP) ; save registers
; first grab MyPalette and myCTab and compare them to nil
Move.L srcPalette(A6),A2 ; get source into A2
CmpA #Nil,A2 ; is it nil?
Beq.S GoHome ; punt if no palette AWC.PB377
Move.L dstCTab(A6),A3 ; get destination into A3
CmpA #Nil,A3 ; is it nil?
Beq.S GoHome ; punt if no ctab AWC.PB377
; leave size in D0; dereference both handles and capture pmEntries
Move.L (A2),A0 ; dereference myPalette
MoveQ #0,D3 ; clear high word
Move pmEntries(A0),D3 ; get number of palette entries
Move.L D3,D0 ; copy length
AddQ.L #1,D0 ; add 1 for the header
Lsl.L #3,D0 ; multiply by size of ColorSpec
Move.L A3,A0 ; put handle in A0
_SetHandleSize ; resize it
Bne.S GoHome ; <> 0 => couldn't handle it AWC.PB377
Move.L (A2),A0 ; redereference myPalette
Move.L (A3),A1 ; dereference CTab
Move D3,D0 ; copy size to a temp
SubQ #1,D0 ; ctSize is really last entry
; CHECK - what should we do with the seed? Get name of call from Ernie, again.
Clr.L ctSeed(A1) ; clear seed
Move D0,ctSize(A1) ; set size
Clr TransIndex(A1) ; this is not a device ColorTable (clear hi bit)
AddQ #ctTable,A1 ; bump color table to start
AddA #pmInfo,A0 ; bump palette to start
MoveQ #0,D1 ; clear index for pixel value
Bra.S CopyEnd ; jump to start of copy
CopyLoop Move D1,value(A1) ; set pixel value
Move.L ciRGB(A0),RGB(A1) ; copy red and green
Move ciRGB+blue(A0),RGB+blue(A1) ; copy blue
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
AddQ #1,D1 ; bump pixel value
CopyEnd DBra D3,CopyLoop ; loop for all entries
GoHome MoveQ #0,D0 ; clear error condition
MoveM.L (SP)+,D3/A2-A3 ; restore registers <AWC>
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE ClearOne(eInfo:CiInfo; BasePtr:Ptr); LOCAL;
;
ClearOne PROC EXPORT
ParamSize equ 4 ; total bytes of params
eInfo equ ParamSize+8-4 ; entry to clear
BasePtr equ eInfo-4 ; pointer to PMgrHandle^^
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L A2,-(SP) ; save a register
Move.L eInfo(A6),A0 ; get the ColorInfo address
Move ciPrivate(A0),D0 ; get the current link information
Clr ciFlags(A0) ; shut down any crap
Clr ciPrivate(A0) ; clear it
Move.L BasePtr(A6),A1 ; set up DevListPtr
Lea DevHandles(A1),A2 ; A2 points at DevHandles
AddA.L #LinkTabs,A1 ; A1 points at LinkTabs
NextLink BfExtU D0{19:5},D1 ; grab device number (0..31)
BfExtU D0{24:8},D2 ; grab index number (0..255)
Move.L (A2,D1.W*8),A0 ; get the device handle
Move.L (A0),A0 ; dereference it
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),A0 ; get handle to CTab
Move.L (A0),A0 ; dereference CTab
Cmp ctSize(A0),D2 ; is index number <= entries - 1?
Bhi.S IgnoreIt ; no => don't unreserve it
Clr ctTable+value(A0,D2.W*8) ; unreserve it
IgnoreIt Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A1,D1.L*4),A0 ; point A0 at next forward link
Move ForeLink(A0),D0 ; get next link
Clr.L ForeLink(A0) ; clear it for the next guy
Tst D0 ; is there another link to examine?
Bmi.S NextLink ; yes => go unlink it
Move.L (SP)+,A2 ; restore A2
Unlk A6 ; clean up our mess
Rtd #ParamSize ; go home
;---------------------------------------------------
;
; PROCEDURE CopyPalette(srcPalette,dstPalette: PaletteHandle; srcEntry,dstEntry,dstLength:
; INTEGER); INLINE $AAA1;
;
CopyPalette PROC EXPORT
ParamSize equ 14 ; total bytes of params
srcPalette equ ParamSize+8-4 ; source Palette handle
dstPalette equ srcPalette-4 ; destination palette handle
srcEntry equ dstPalette-2 ; source starting entry
dstEntry equ srcEntry-2 ; destination starting entry
dstLength equ dstEntry-2 ; length of the copy
TrimLen equ -2
VarSize equ TrimLen
Link A6,#VarSize ; build stack frame
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
Move.L PMgrHandle,A4 ; get the main handle
CmpA.L #PMgrNil,A4 ; are we initialized?
Beq GoHome ; no => punt AWC.PB377
Move.L dstPalette(A6),A2 ; get destination palette
CmpA.L #Nil,A2 ; is it nil?
Beq GoHome ; can't deal with nil here either AWC.PB377
Move.L srcPalette(A6),A3 ; get source palette
CmpA.L #Nil,A3 ; is it nil?
Beq GoHome ; can't deal with a nil handle AWC.PB377
CmpA.L A2,A3 ; does source = destination?
Beq GoHome ; we can't handle this yet AWC.PB377
MoveQ #0,D0 ; clear D0
Move dstLength(A6),D0 ; get the length of the copy
Ble GoHome ; we can quit if it's too small
Move.L D0,D3 ; copy the length
Add SrcEntry(A6),D0 ; D0 is the required length of the source
Move.L (A3),A1 ; dereference source palette
Move pmEntries(A1),D1 ; get size of source palette
Sub D0,D1 ; D1, if negative, is how much we must trim D3
Bpl.S DontTrimSrc ; no => don't trim it
Add D1,D3 ; trim back the length of the copy AWC.PB530
DontTrimSrc Move.L (A2),A0 ; dereference the destination
Move pmEntries(A0),D4 ; get the length
Move DstEntry(A6),D0 ; calculate the potential new pmEntries
Add D3,D0 ; by adding the trimmed length
Cmp D4,D0 ; need we add handle room?
Ble.S BigEnough ; no => skip _SetHandleSize AWC.PB530
Move D0,D4 ; save new length
Move.L A2,A0 ; copy DstPalette
AddQ #1,D0 ; include palette header
Asl #4,D0 ; multiply by 16 bytes per entry | header
_SetHandleSize ; do it
Bne GoHome ; and quit if we couldn't do it AWC.PB377
Move.L (A2),A0 ; dereference the destination handle
Move D4,D2 ; make a copy of the new length
MoveQ #0,D1 ; clear the high word
Move PmEntries(A0),D1 ; this is where to start clearing
Sub D1,D2 ; this is now many to clear
Move D4,pmEntries(A0) ; save size
Lea PmInfo(A0),A1 ; point us at the start of the table
Asl #4,D1 ; this is the offset to the start of the clear
AddA.L D1,A1 ; bump A1 to the start of the clear
Bra.S ClearEnd ; jump to the DBra
; The main reason for clearing is so we can correctly detect and clear entries that are
; going to be clobbered.
ClearLoop Clr.L (A1)+ ; clear 16 bytes
Clr.L (A1)+
Clr.L (A1)+
Clr.L (A1)+
ClearEnd DBra D2,ClearLoop
BigEnough CmpA.L A2,A3 ; does SrcPalette = DstPalette?
Beq.S GoHome ; yes => can't handle this AWC.PB377
Move.L A3,-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
Move.L (A3),A1 ; dereference source palette
MoveQ #0,D0 ; clear the high word
Move DstEntry(A6),D0 ; get the first destination
Asl.L #4,D0 ; multiply by 16
Move.L (A2),A0 ; dereference destination palette again AWC.PB508
Lea PmInfo(A0,D0),A0 ; point A0 at the first destination
MoveQ #0,D1 ; clear the high word
Move SrcEntry(A6),D0 ; get the first source
Asl.L #4,D0 ; point A0 at the first destination
Lea PmInfo(A1,D0),A1 ; point A1 at the first source
Bra.S CopyEnd ; jump into the loop
CopyLoop Move ciPrivate(A0),D0 ; get the link info
Beq.S NoLinks ; no => it doesn't need clearing
MoveM.L A0-A1,-(SP) ; save registers
Move.L A0,-(SP) ; ciInfo to clear
Move.L (A4),-(SP) ; dereference PMgrHandle and push it
Jsr ClearOne ; clear the links
MoveM.L (SP)+,A0-A1 ; restore interesting registers
NoLinks Move.L ciRGB(A1),ciRGB(A0) ; copy first two words
Move.L ciRGB+Blue(A1),ciRGB+blue(A0) ; copy blue and usage
Move ciTolerance(A1),ciTolerance(A0) ; copy tolerance
Clr ciFlags(A0) ; clear the flags field
Clr ciPrivate(A0) ; clear the links field
AddA.L #CiSize,A0 ; bump both pointers
AddA.L #CiSize,A1
CopyEnd DBra D3,CopyLoop ; loop for (trimmed) length entries
GoHome MoveQ #0,D0 ; clear error code AWC.PB377
MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE UpdateDevice(DeviceNumber:INTEGER); Local;
;
; This here routine will do a setentries of deviceNumber on it's own color table.
; Also, it forces a redraw of that screen, including the menu bar.
; (This code was moved out of the tail of SetDev, so that ScatterDev could use it.)
; <dvb3>
;
UpdateDevice PROC EXPORT
UDVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result length: none
deviceNum DS.B 2 ;Input: device number
return DS.B 4
A6Link DS.B 4 ;old contents of A6
oldPort DS.B 4 ;pointer to old port
resultRect DS.B 8 ;a temp rectangle
sysUpdates DS.B 2 ;a temp boolean
linkSize DS.B 0 ;linky number
ENDR
WITH UDVars
LINK A6,#linkSize
MOVEM.L A0-A3/D0-D3,-(SP)
SUBQ #4,SP
_FrontWindow
MOVE.L (SP)+,D3 ; D3 = topmost window. Permanently.
Pea oldPort(A6) ; where to put current GrafPtr
_GetPort ; get it
MOVE.L PMgrHandle,A1 ; A1 = handle to palette data
MOVE.L (A1),A1 ; A1->palette data
MOVE deviceNum(A6),D0 ; D0 = device number to update
MOVE.L devHandles+devHandle(A1,D0.W*8),A2 ; A2 = handle to device to update
MOVE.L A2,A0 ; Put in A0, for devsetent
JSR DevSetEntries
Move.L (A2),A0 ; dereference it
Lea gdRect(A0),A2 ; get address of device rect into A2
Move gdFlags(A0),D0 ; get flags
BTst #MainScreen,D0 ; is it the main screen?
Beq.S NoMenuFix ; no => don't update the menu
Move.L MenuList,D0 ; get the MenuList handle; is it nil? AWC.PB508
Beq.S NoMenuFix ; yes => don't redraw the menu bar AWC.PB508
Move.L D0,A0 ; get ready to dereference it AWC.PB508
Tst.L (A0) ; has it been purged? AWC.PB508
Beq.S NoMenuFix ; yes => don't redraw the menu bar AWC.PB508
_DrawMenuBar ; redraw the menu bar AWC.PB508
NoMenuFix MoveQ #0,D0 ; we want no updates if no SysPalette AWC PB223
Move.L AppPalette,A0 ; fetch the application's palette, if any AWC.PB457
Move.L A0,D1 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
Bne.S UseAppPltt ; no => use the application's palette AWC.PB457
MOVE.L PMgrHandle,A0
MOVE.L (A0),A0 ; A0 -> our data
Move.L SysPalette(A0),A0 ; fetch the system palette
Move.L A0,D1 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
Beq.S NoSysP ; yes => we update
UseAppPltt Move.L (A0),A0 ; dereference AppPalette or SysPalette AWC.PB457
Move pmPrivate(A0),D0 ; get update information AWC PB224
And #$C000,D0 ; and it with the proper flags AWC PB224
NoSysP Move D0,sysUpdates(A6) ; set update information AWC PB224
JSR CheckForJuggler ; ¿Are we Juggling?
Bne.S NotJuggling ; no => handle updates the old way AWC PB224
Move.L A2,-(SP) ; push device rect on the stack AWC PB224
Move deviceNum(A6),-(SP) ; push PaletteMgr device number AWC PB224
Move sysUpdates(A6),-(SP) ; push default updates for old ports AWC PB224
Move #ColorInvalRect,-(SP) ; push the selector for _ColorInvalRect AWC PB224
_Juggler ; call Erich's disgusting C code AWC PB224
bra EndJuggling ; skip over the regular update code AWC PB224
NotJuggling Move.L WindowList,A3 ; get start of window list AWC PB224
CMPA #-1,A3 ; Window list there?
BEQ WLDone ; No, fini.
BRA EndWind ; Skip to end, for NIL check
WindowLoop Move sysUpdates(A6),D1 ; reset the default update value AWC.PB480
Move #CBackBit,D0 ; grab a constant AWC PB224
CmpA.L D3,A3 ; is it the "fore" window?
Bne.S NotCurrent ; no => check for background updates
Move #CForeBit,D0 ; grab a different constant AWC PB223
NotCurrent Tst.B wVisible(A3) ; is this window visible?
Beq NextWind ; no => do the next window <C864>
Tst PortBits+RowBytes(A3) ; is it a color window?
Bpl.S UseDefault ; no => handle an old style window AWC.PB480
Move.L GrafVars(A3),A0 ; get the extended variables handle
Move.L (A0),A0 ; dereference it
Move.L PmFgColor(A0),A0 ; get the window's palette, if any
CmpA.L #Nil,A0 ; is it nil?
Beq.S UseDefault ; yes => default to the system value AWC.PB480
Move.L (A0),A0 ; dereference the palette
Move pmPrivate(A0),D1 ; fetch the palette's update values AWC.PB480
UseDefault BTst D0,D1 ; does the caller want this update? AWC.PB480
Beq.S NextWind ; no => do the next window
; We now must check to see if the window we're examining intersects the device
; we're working upon. We'll GlobalToLocal the device rect and simultaneously
; intersect it with the window's portRect. If we detect an intersection then
; we'll have calculated the rectangle we'll need for the InvalRect. First we
; point A0 at the Bounds rect for the port so we can put DevRect in local space.
Lea PortBits(A3),A0 ; point A0 at potential bitmap AWC.PB480
Tst RowBytes(A0) ; bitmap or pixmap? AWC.PB480
Bpl.S GotBitmap ; no high bit in Rowbytes => bitmap AWC.PB480
Move.L BaseAddr(A0),A0 ; get Port's Pixmap handle AWC.PB480
Move.L (A0),A0 ; get Pixmap pointer AWC.PB480
GotBitmap Lea Bounds(A0),A0 ; advance A0 to Bounds rect AWC.PB480
Move Top(A2),D0 ; get device top AWC.PB480
Add Top(A0),D0 ; subtract bounds top AWC.PB480
Cmp PortRect+Bottom(A3),D0 ; is Dest.Top >= Port.Bottom? AWC.PB480
Bge.S NextWind ; yes => no intersection AWC.PB480
Move D0,resultRect+Top(A6) ; save it AWC.PB480
Move Left(A2),D0 ; get device left AWC.PB480
Add Left(A0),D0 ; subtract bounds left AWC.PB480
Cmp PortRect+Right(A3),D0 ; is Dest.Left >= Port.Right? AWC.PB480
Bge.S NextWind ; yes => no intersection AWC.PB480
Move D0,resultRect+Left(A6) ; save left AWC.PB480
Move Bottom(A2),D0 ; get bottom AWC.PB480
Add Top(A0),D0 ; subtract bounds top AWC.PB480
Cmp PortRect+Top(A3),D0 ; is Dest.Bottom <= Port.Top? AWC.PB480
Ble.S NextWind ; yes => no intersection AWC.PB480
Move D0,resultRect+Bottom(A6) ; save bottom AWC.PB480
Move Right(A2),D0 ; get right AWC.PB480
Add Left(A0),D0 ; subtract bounds left AWC.PB480
Cmp PortRect+Left(A3),D0 ; is Dest.Right <= Port.Left? AWC.PB480
Ble.S NextWind ; yes => no intersection AWC.PB480
Move D0,resultRect+Right(A6) ; save right AWC.PB480
Move.L A3,-(SP) ; push this window's pointer AWC.PB480
_SetPort ; make it the current port AWC.PB480
Pea resultRect(A6) ; move device rect (local) onto the stack AWC.PB480
_InvalRect ; invalidate it AWC.PB480
NextWind Move.L NextWindow(A3),A3 ; grab the next window in the list
EndWind CmpA.L #Nil,A3 ; is it nil?
Bne WindowLoop ; no => continue
Bsr RedrawDesktop ; redraw the desktop (uses A3) AWC.PB508
WLDone
EndJuggling Move.L oldPort(A6),-(SP) ; push old port
_SetPort ; restore old port
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
MoveM.L (SP)+,A0-A3/D0-D3 ; restore registers <AWC>
UNLK A6
RTD #result-return-4 ; bye.
;---------------------------------------------------
;
; PROCEDURE UpdateDevices(); LOCAL;
;
; Update all devices with bits in updateDevs.
UpdateDevices PROC EXPORT
MOVEM.L A0/D0-D1,-(SP)
CMPI.L #-1,WindowList ; Have Windows happened?
BEQ.S GoHome ; No=>skip this stuff
CMPI.L #-1,CurApName ; Is CurApName FFFFFFFF?
BEQ.S GoHome ; If so, we can't help yet.
MOVE.L PMgrHandle,A0
MOVE.L (A0),A0 ; A0->PMgr data
MOVE nDevs(A0),D0 ; D0 = number of devices
SUBQ #1,D0 ; less one for DBRAing
MOVE.L updateDevs(A0),D1 ; D1 = mask of devices to update
BEQ.S GoHome ; None. Bye.
CLR.L updateDevs(A0) ; Say they've been updated.
UpLoop BTST D0,D1 ; Update this one?
BEQ.S UpLoopEnd ; Nah.
MOVE D0,-(SP) ; Yah. Push device number (stack down 2)
JSR UpdateDevice
UpLoopEnd DBRA D0,UpLoop
GoHome MOVEM.L (SP)+,A0/D0-D1 ; fix regs
RTS
;---------------------------------------------------
;
; FUNCTION WhatPal(aWindow:WindowPtr):PaletteHandle; LOCAL; AAA2/5
;
; Given window in A2, return its palette, or appPalette, or even sysPalette
WhatPal PROC EXPORT
MOVE.L 4(SP),A0 ; A0 = aWindow
TST portBits+rowBytes(A0) ; An old port?
BPL.S @default ; Yes => go use sys- or app-palette
MOVE.L GrafVars(A0),A0
MOVE.L (A0),A0 ; A0->aux data
MOVE.L PmFgColor(A0),D0 ; D0 = specified Palette
BNE.S @goHome ; Nil? No => we got a palette
@default MOVE.L AppPalette,D0 ; Try the AppPalette
BNE.S @goHome ; Yes, got an AppP
MOVE.L PMgrHandle,A0
MOVE.L (A0),A0
MOVE.L SysPalette(A0),D0 ; D0 = System Palette
@goHome MOVE.L D0,8(SP)
RTD #4
;---------------------------------------------------
;
; PROCEDURE CalcDevs; LOCAL;
;
; Set DeviceSet(A6) and FrontSet(A6) to the bit-set of the
; devices that PaletteH(A6) affects.
;
CalcDevs PROC EXPORT
MOVEM.L D3-D7/A2-A3,-(SP) ; Restore registers
SUBQ #8,SP ; Make space for a temp rect
MOVE.L WindowList,A2 ; A2 = Windowlist walker
MoveQ #0,D3 ; clear device set
MoveQ #0,D4 ; clear front set
CLR.L -(SP) ; Space for result
_FrontWindow
MOVE.L (SP)+,D6 ; Keep the frontwindow in here.
BRA @wLoopEnd ; Branch to end of window walking
@wLoop TST.B wVisible(A2) ; A visible window?
; BEQ @wLoopNext ; No. Ignore it. <dvb11>:inv'ble w'dws can have colors
SUBQ #4,SP
MOVE.L A2,-(SP)
_WhatPal
MOVE.L (SP)+,A0
CMPA.L PaletteH(A6),A0 ; Same one we're activating?
BNE @wLoopNext ; No, don't check it.
LEA portBits(A2),A0 ; A0->bitmap
TST rowBytes(A0) ; Old port?
BPL @oldPort ; Yes=>skip pm dereference
MOVE.L baseAddr(A0),A0 ; A0 = pixmap handle
MOVE.L (A0),A0 ; A0->pixmap
@oldPort MOVE.L bounds(A0),D0 ; D0 = top, left of bounds rect
MOVE.L portRect(A2),D1 ; D1 = top, left of port rect
SUB D0,D1 ; D1Lo = global left
SWAP D0
SWAP D1
SUB D0,D1 ; D1Lo = global top
SWAP D0
SWAP D1
MOVE.L D1,WindowRect(A6) ; WindowRect topLeft in global
MOVE.L portRect+botRight(A2),D1 ; D1 = bottom, right of port rect
SUB D0,D1 ; D1Lo = global right
SWAP D0
SWAP D1
SUB D0,D1 ; D1Lo = global bottom
SWAP D1
MOVE.L D1,botRight+WindowRect(A6) ; WindowRect botRight in global
MOVE.L PMgrPtr(A6),A0 ; A0->Pmgr data
MOVE nDevs(A0),D5 ; D5 = device number
SUBQ #1,D5
LEA DevHandles(A0),A3 ; A3->List of devices
@dLoop MOVE.L DevHandle(A3,D5*8),A0 ; A0 = this device handle
MOVE.L (A0),A0 ; A0->this device
CLR -(SP) ; Space for result
PEA gdRect(A0) ; Push device rect
PEA WindowRect(A6) ; Push window rect
PEA 10(SP) ; Push throwaway result rect
_SectRect
TST (SP)+ ; Any intersection?
BEQ.S @dLoopEnd ; No=>advance to next gDevice
BSET D5,D3 ; Set this bit of deviceSet
TST.B wHilited(A2) ; Is this window hilited?
BEQ.S @notFront ; If not, can't be frontish
CMP.L A2,D6 ; Is this window the FrontWindow?
BNE.S @wasntFront ; No => go here
MOVE.L A2,DevFrontMost(A3,D5*8) ; Yes => save it.
BRA.S @wasFront
@wasntFront CMPA.L DevFrontMost(A3,D5*8),A2 ; was it previously frontmost?
BNE.S @notFront ; No, not front at all.
@wasFront BSET D5,D4 ; Set this bit of FrontSet
@notFront
@dLoopEnd DBRA D5,@dLoop ; Try next device
@wLoopNext MOVE.L NextWindow(A2),A2 ; Get next window
@wLoopEnd MOVE.L A2,D0 ; NIL window?
BNE @wLoop ; No=>Loop!
MOVE.L D3,DeviceSet(A6) ; Save device set
MOVE.L D4,FrontSet(A6) ; Save frontmost set
ADDQ.L #8,SP ; Lose temp rectangle
MOVEM.L (SP)+,D3-D7/A2-A3 ; Restore registers
RTS
;---------------------------------------------------
;
; PROCEDURE UnhookDevice(whichDevice:deviceHandle);
;
; InitGDevice ought to call this routine. When a device is initialized, release any animated
; entries, and give it our idea of an appropriate clut.
UnhookDevice PROC EXPORT
ParamSize equ 4 ; total bytes of params
whichDevice equ ParamSize+8-4 ; device we're unlinking
Link A6,#spVarSize ; build stack frame
MOVEM.L D2-D4/A2,-(SP)
Move.L PMgrHandle,A0 ; get global handle
CmpA.L #PMgrNil,A0 ; is it nil?
Beq.S GoHome ; skip it
Move.L (A0),A0 ; dereference PMgrHandle
Move nDevs(A0),D3 ; are there any devices?
LEA DevHandles(A0),A1 ; A1 = start of list of devices, D4=count
MOVE.L whichDevice(A6),D1 ; D1 = device handle to fix release links of
SUBQ #1,D3 ; for DBRA (nDevs says we've got some devs)
FindDevLoop CMP.L DevHandle(A1,D3.W*8),D1 ; Is this the device?
BEQ.S FoundDevice
DBRA D3,FindDevLoop
BRA.S GoHome ; It's not a device we know about.
FoundDevice LSL.W #8,D3 ; Shift device number into high bits
MOVE.L D1,A2 ; A2 = device we're zapping
MOVE.L (A2),A2 ; dereference device
MOVE.L gdPMap(A2),A2 ; A2 = PixMapHandle
MOVE.L (A2),A2 ; dereference pmhandle
MOVE.L pmTable(A2),A2 ; A2 = cluthandle
MOVE.L (A2),A2 ; dereference that, too
MOVE #255,D4 ; We'll just unlink all 256 entries of the linktab.
ZapLoop MOVE.B D4,D3
MOVE.W D3,-(SP) ; Push combinded index and device
_ZapLinks ; Unlink device/index combo
ZapLoopEnd DBRA D4,ZapLoop
SUB #2,SP ; Space for result
MOVE.L D1,-(SP) ; Push device handle
JSR CheckDeviceColors ; Look for the right colors
TST (SP)+ ; Anything reallocated?
BEQ.S GoHome ; No=>nothing
CLR.L D0
LSR.W #8,D3 ; Get back device number
BSET D3,D0 ; D0 = 1 bit set in the device's position
OR.L D0,scatterDevs(A0) ; Tell ourselves to deal with that device.
MOVE #1,-(SP)
JSR ScatterDevices ; And scatter entries.
;!!! MOVE D3,-(SP) ; Push device number
;!!! JSR UpdateDevice ; Update this device.
GoHome MOVEM.L (SP)+,D2-D4/A2
UNLK A6
RTD #paramSize ; Bus on out of here.
;---------------------------------------------------
;
; PROCEDURE UnreserveDevices(PMgrPtr,PalettePtr,Devmask);
;
; Call me to unreserve entries when a palette has moved from one place to another.
; We have ActivatePalettes A6 frame, also, on entry, we have
; A0->Pmgr data, A1->palette, D0 = devmask
; <dvb3>
UnreserveDevices PROC EXPORT
MOVEM.L A2-A4/D1-D4,-(SP)
LEA LinkTabs(A0),A2 ; A2 -> linktabs
MOVE pmEntries(A1),D1 ; D1 = loop variable
LEA pmInfo(A1),A3 ; A3 = walking ColorInfo pointer
CLR.L D4 ; D4 = device mask for later scattering
BRA.S entryEnd
entryLoop MOVE ciPrivate(A3),D2 ; D2 = LinkTab entry (if any)
BPL.S nextEntry ; If positive, it owns no entries.
devLoop BFEXTU D2{19:5},D3 ; D3 = device number
BTST D3,D0 ; A device we should 'clear'?
BEQ.S nextDev ; No, keep walking
BSET D3,D4 ; Mark device for scattering
MOVE.L D0,-(SP) ; preserve D0
MOVE D2,-(SP) ; Push Device/Index
_ZapLinks ; Unlink it
MOVE.L (SP)+,D0 ; restore D0
MOVE.L DevHandles+DevHandle(A0,D3*8),A4 ; A4 = device handle
BFEXTU D2{24:8},D3 ; D3 = index
Move.L (A4),A4 ; dereference it
Move.L gdPMap(A4),A4 ; get handle to pixmap
Move.L (A4),A4 ; dereference pixmap
Move.L pmTable(A4),A4 ; get handle to CTab
Move.L (A4),A4 ; dereference CTab
Cmp ctSize(A4),D3 ; is index number <= entries - 1?
Bhi.S nextDev ; no => don't unreserve it
MOVE #ctScatterVal,ctTable+value(A4,D3.W*8) ; unreserve it, mark scatterbit <dvb3>
nextDev AND #$1FFF,D2 ; Mask off the key bits
MOVE ForeLink(A2,D2.W*4),D2 ; Get next link item
BMI.S devLoop ; End of list, eh?
nextEntry ADDA #ciSize,A3
entryEnd DBRA D1,entryLoop
OR.L D4,scatterDevs(A0)
MOVEM.L (SP)+,A2-A4/D1-D4
RTS
;---------------------------------------------------
;
; PROCEDURE ZapLinks(myIndex:integer); LOCAL; AAA2/4
;
; If index myIndex (combined device and index) is linked by someone, break the link
; and mark it free. Decrement the "reserves" count of the palette who
; owns the index. Pass myIndex with device in high bits, index in low bits.
; (This code was moved out of Pillage <dvb>)
; (See how we courteously restore ALL registers)
ZapLinks PROC EXPORT
ZLVars RECORD {A6Link},DECREMENT
result DS.B 0 ;Result length: none
myIndex DS.B 2 ;Input: device number and index to unlink
return DS.B 4
A6Link DS.B 4 ;old contents of A6
linkSize DS.B 0 ;linky number
ENDR
WITH ZLVars
LINK A6,#linkSize
MOVEM.L A0-A2/D0-D4,-(SP)
MOVE.L PMgrHandle,A1
MOVE.L (A1),A1 ; A1->PMgrData
LEA LinkTabs(A1),A0 ; A0->Link Tables
MOVE.L PListHandle(A1),A2 ; A2 = palette list handle
MOVE.L (A2),A2 ; A2 -> palette info list
MOVE myIndex(A6),D0 ; D0 = tricky link
AND #$1FFF,D0 ; clear key bits
MOVE D0,D1
LSR #8,D1 ; D1 = device number
MOVE.L DevHandles(A1,D1*8),A1 ; A1 = device handle
MOVE.L (A1),A1 ; A1->device
MOVE.L gdPMap(A1),A1 ; A1 = pixmap handle
MOVE.L (A1),A1 ; A1->pixmap
MOVE.L pmTable(A1),D1 ; D0 = color table for this device
BEQ.S @a ; Skip this if none
MOVE.L D1,A1 ; A1 = color table handle
MOVE.L (A1),A1 ; A1 -> color table
CLR D1
MOVE.B D0,D1 ; We need to clear the upper bits
CMP ctSize(A1),D1 ; Index in range? <dvb - was D0, WRONG!>
BHI.S @a ; No=>skip this
BCLR #ctReserveBit,ctTable+value(A1,D1*8) ; unreserve!
@a
Move ForeLink(A0,D0.W*4),D3 ; get forward links
BEQ GoHome ; Hey! this link was unowned anyhow! <dvb3>
Move BackLink(A0,D0.W*4),D4 ; get backward links
Clr.L (A0,D0.W*4) ; clear the links away
Tst D3 ; examine forward link
Bmi.S MultiLinks1 ; if < 0 we have more than one assigned
Tst D4 ; examine backward link
Bmi.S MultiLinks2 ; if < 0 we have more than one assigned
; This was a quickie. D3 contains the palette number, D4 the entry number. All we
; need do is tell the palette it no longer has it.
And #$1FFF,D3 ; clear key bits
SubQ #1,Reserves(A2,D3*8) ; it has one less entry reserved
Move.L PaletteRef(A2,D3*8),A0 ; get the palette
Move.L (A0),A0 ; dereference it
And.L #$00001FFF,D4 ; clear high word and key bits
Lsl.L #4,D4 ; make it an offset to the ColorInfo
Clr pmInfo+ciPrivate(A0,D4.L) ; clear the link
Bra GoHome ; we did it!
; The forward link goes somewhere. See if the backward one does too. If so,
; jump to BothLinks.
MultiLinks1 Tst D4 ; examine backward link
Bmi.S BothLinks ; both of them go somewhere
; The forward link goes somewhere, but the backward one does not. We must remember
; the first forward link so we can copy it into the palette, then we advance
; forward by one, copy the palette entry into that, and continue searching until we find
; out what palette this is.
Move D3,D0 ; remember the forward link
BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next forward link
Move D4,BackLink(A1) ; copy the back link
Move ForeLink(A1),D3 ; get next link
Bpl.S GotPalette1 ; if > 0, we've found the palette
MultiFLoop BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move ForeLink(A0,D1.L*4),D3 ; get next link; is it positive?
Bmi.S MultiFLoop ; no => continue
GotPalette1 And #$1FFF,D3 ; clear key bits
SubQ #1,Reserves(A2,D3*8) ; it has one less entry reserved
Move.L PaletteRef(A2,D3*8),A0 ; get the palette
Move.L (A0),A0 ; dereference it
And.L #$00001FFF,D4 ; clear high word of entry
Lsl.L #4,D4 ; make it an offset to the ColorInfo
Move D0,pmInfo+ciPrivate(A0,D4.L) ; set a new link
Bra.S GoHome ; we did it!
; The backward link goes somewhere, but the forward one does not. We must advance
; backward by one, copy the palette id into it, and continue searching until we find out
; what palette this is.
MultiLinks2 BfExtU D4{19:5},D1 ; grab device number (0..31)
BfExtU D4{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next backward link
Move D3,ForeLink(A1) ; copy the forward link
Move BackLink(A1),D4 ; get next link
Bpl.S GotPalette2 ; if > 0, we've found the palette
MultiBLoop BfExtU D4{19:5},D1 ; grab device number (0..31)
BfExtU D4{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move BackLink(A0,D1.L*4),D4 ; get next link; is it positive?
Bmi.S MultiBLoop ; no => continue
Bra.S GotPalette2 ; share common code
; We're in the middle of the list somewhere. We'll step one backward and copy
; the forelink from the current entry, then we'll step one foreward and copy
; the backlink from the current entry. Then we'll keep going forward until we
; find the palette. All we need do is decrement its reference count, so we don't
; need the entry number.
BothLinks BfExtU D4{19:5},D1 ; grab device number (0..31)
BfExtU D4{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next backward link
Move D3,ForeLink(A1) ; copy the forward link
BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next foreward link
Move D4,BackLink(A1) ; copy the backward link
Move ForeLink(A1),D3 ; get next foreward link
Bpl.S GotPalette2 ; if > 0, we've found the palette
BothLoop BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move ForeLink(A0,D1.L*4),D3 ; grab next forward link
Bmi.S BothLoop ; if < 0, we keep looking
GotPalette2 And #$1FFF,D3 ; clear away key bits
SubQ #1,Reserves(A2,D3*8) ; it has one less entry reserved
GoHome MOVEM.L (SP)+,A0-A2/D0-D4
UNLK A6
RTD #result-return-4 ; go home
;---------------------------------------------------
;
; PROCEDURE ResizePalette(srcPalette:PaletteHandle; dstSize:INTEGER); AAA2/3;
;
; Set the number of entries in the palette, and properly dispose of some
; of them if the palette is shrinking.
ResizePalette PROC EXPORT
RPVars RECORD {A6Link},DECREMENT
result DS.B 0 ; Result: none
srcPal DS.B 4 ; input: palette handle
dstSize DS.B 2 ; input: new size for palette
return DS.B 4
A6Link DS.B 4 ; old contents of A6
linkSize DS.B 0 ;linky number
ENDR
WITH RPVars
LINK A6,#linkSize
MOVEM.L A2/D3-D4,-(SP) ; save 'em.
IF (forRom OR theFuture) THEN
; clear out d3,d4 for later use
moveq #0,d3 ;<SM2> FM This ensures that the high
move.l d3,d4 ;<SM2> FM word is zeroed out before the compare
ENDIF
MOVE.L srcPal(A6),A0 ; A0 = palette we're resizing
MOVE.L A0,D0
ADDQ.L #1,D0 ; Was it Ptr(-1)? The App Palette?
BNE.S @foundPal ; No=>it's a real one
MOVE.L AppPalette,A0 ; Get the 'app palette'
@foundPal MOVE.L (A0),A2 ; A2->the palette
MOVE dstSize(A6),D3 ; D3 = new size for palette
MOVE pmEntries(A2),D4 ; D4 = old size of palette
CMP D4,D3 ; Compare new size to old size
BEQ.S @goHome ; The same, do nothing
BHI.S @sizeIt ; It's bigger, resize and fix new entries
_HLock ; If we're shrinking, we have to lose entries
MOVE.L (A0),A2 ; A2->locked palette
MOVE D4,D0 ; D0 = old size of palette
LSL #4,D0 ; Multiply by size of colorInfos
LEA pmInfo(A2,D0.W),A2 ; A2->just past last colorInfo
@loseLoop SUBA #ciSize,A2 ; Bump A2 down to next colorInfo
SUBQ #1,D4 ; Bump D4 down to next entry number
MOVE ciUsage(A2),D0 ; D0 = usage for this entry
ANDI #pmTolerant+pmAnimated,D0 ; Anything we care about?
BEQ.S @loseEnd ; No, continue
MOVE.L srcPal(A6),-(SP) ; Yes => set usage to courteous, before death
MOVE D4,-(SP) ; Push entry number
CLR.L -(SP) ; 0 usage, 0 tolerance (its the law)
_SetEntryUsage
@loseEnd CMP D4,D3
BNE.S @loseLoop ; Work right down to new size
MOVE.L srcPal(A6),A0 ; Get handle back
_HUnlock
@sizeIt MOVE D3,D0 ; D0 = new number of entries
EXT.L D0 ; long, for resize
LSL.L #4,D0 ; times size of colorInfos
ADD.L #pmInfo,D0 ; Plus size of header
_SetHandleSize
BNE.S @goHome ; Failed, go home.
MOVE.L (A0),A2 ; A2->palette
MOVE D3,pmEntries(A2) ; Set new palette size
CMP.w D3,D4 ; Was old size smaller? <KON 17May90>
BHS.S @goHome ; old size (D4) was bigger, or the same
SUB.L D4,D3 ; D3 = difference in sizes
LSL #4,D4 ; Get D4 to size*colorInfo size
LEA pmInfo(A2,D4),A0 ; A0->first newly added entry
LSL #2,D3 ; D3 = difference in sizes in longwords
SUBQ #1,D3 ; Less one, for DBRA
@clrLoop CLR.L (A0)+ ; Clear a long
DBRA D3,@clrLoop ; Keep on clearing
@goHome MOVEM.L (SP)+,A2/D3-D4
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
; PROCEDURE RestoreDeviceClut(aGDev:gDevice); AAA2/2;
;
; Set the specified device back to its default clut, based on depth
; and color/gray. If direct, ignore it. Actually, "UnhookDevice"
; does all the real work here, we just provide a loop to do it
; to all the devices if NIL is passed.
;
RestoreDeviceClut PROC EXPORT
TST.L 4(SP) ; Was NIL passed?
BNE UnhookDevice ; Yes => just pass on to Unhookdevice
MOVE.L A3,-(SP) ; Save a walking register
MOVE.L deviceList,D0 ; Get head of devicelist
BRA.S @devLoopEnd ; Go to end of list
@devLoop MOVE.L D0,A3
MOVE.L A3,-(SP) ; Push device handle
BSR UnhookDevice
MOVE.L (A3),A3 ; Dereference gDev handle
MOVE.L gdNextGD(A3),D0 ; Get next gdev handle
@devLoopEnd BNE.S @devLoop ; NIL?
MOVE.L (SP)+,A3 ; Yeah, fix register.
RTD #4 ; We're out, lose input handle.
;---------------------------------------------------
;
; PROCEDURE NewHiliteColor; AAA2/11;
;
; Call here when the hilite-color has been changed. Screens will be appropriately
; zapped.
NewHiliteColor PROC EXPORT
MOVE.L PMgrHandle,D1 ; PMgr active?
BEQ.S cancel
MOVE.L D1,A1
MOVE.L (A1),A1 ; A1->PMgr
MOVE.L sevenCluts+8(A1),D0 ; Have we a two-bit hilite clut?
BEQ.S noTwoBit ; Nah, we're fine
CLR.L sevenCluts+8(A1) ; Okay, it's nil.
MOVE.L D0,A0 ; Yes=>toss it, we'll rebuild.
_DisposHandle
noTwoBit MOVE.L D1,A1 ; A1 = PMgr Handle
MOVE.L (A1),A1 ; A1->PMgr
MOVE.L sevenCluts+16(A1),D0 ; Have we a four-bit hilite clut?
BEQ.S noFourBit ; Nah, we're fine
CLR.L sevenCluts+16(A1) ; Okay, it's nil.
MOVE.L D0,A0 ; Yes=>toss it, we'll rebuild.
_DisposHandle
noFourBit
JSR CheckAllDeviceCluts ; make sure everyone has new HiliteColor
CLR -(SP) ; No setentries on scatter
JSR ScatterDevices ; put some colors out there
JSR UpdateDevices ; Send those InvalRects arounds.
cancel RTS ; bye.
;---------------------------------------------------
;
; PROCEDURE SaveFore(VAR x:ColorSpec); AAA2/13;
; PROCEDURE SaveBack(VAR x:ColorSpec); AAA2/14;
;
; Return a colorspec with the following coding:
; value = 0 - rgb is an rgb color
; value = 1 - rgb.red is the previous palette entry number
;
SaveFore PROC EXPORT
EXPORT SaveBack
MOVEQ #0,D0 ; Tell ourselves it's a Fore
BRA.S save
SaveBack MOVEQ #1,D0 ; Tell ourselves it's a Back
save MOVE.L 4(SP),A1 ; A1->colorSpec to return data in
Move.L GrafGlobals(A5),A0 ; get the QuickDraw globals pointer
Move.L ThePort(A0),A0 ; point at the port
Tst PortBits+Rowbytes(A0) ; is it a new port?
Bpl.S @saveRGB ; no => punt
MOVE.L GrafVars(A0),D1 ; Get aux handle <dvb9>
BEQ.S @SaveRGB ; Not there? puntit
MOVE.L D1,A0 ; <dvb9>
MOVE.L (A0),A0 ; A0->aux data
BTST D0,pmFlags+1(A0) ; Test the appropriate bit fore PM
BEQ.S @SaveRGB ; Okay, it wasn't a PmXxxxColor
MOVE #1,value(A1) ; value=1: a PM save
TST D0 ; Fore or back call
BEQ.S @pmFore
MOVE pmBkIndex(A0),rgb+red(A1) ; Save back entry number
BRA.S @goHome
@pmFore MOVE pmFgIndex(A0),rgb+red(A1) ; Save fore entry number
@goHome RTD #4
@SaveRGB CLR value(A1) ; value=0: an RGB save
PEA rgb(A1) ; Push pointer to rgb
TST D0 ; Fore or back?
BEQ.S @rgbFore
_GetBackColor
BRA.S @goHome
@rgbFore _GetForeColor
BRA.S @goHome
;---------------------------------------------------
;
; PROCEDURE RestoreFore(VAR x:ColorSpec); AAA2/15;
; PROCEDURE RestoreBack(VAR x:ColorSpec); AAA2/16;
;
; Set the fore/back color from a colorspec
; with the following coding:
; value = 0 - rgb is an rgb color
; value = 1 - rgb.red is the previous palette entry number
;
RestoreFore PROC Export
EXPORT RestoreBack
MOVE.L 4(SP),A1 ; A1->Spec to restore
TST (A1)+ ; RGB or PM color?
BNE.S forePM ; PM => do that
PEA (A1) ; RGB => do that
_RGBForeColor
goHome RTD #4
forePM MOVE (A1),-(SP)
_PMForeColor
BRA.S goHome
RestoreBack
MOVE.L 4(SP),A1 ; A1->Spec to restore
TST (A1)+ ; RGB or PM color?
BNE.S backPM ; PM => do that
PEA (A1) ; RGB => do that
_RGBBackColor
BRA.S goHome
backPM MOVE (A1),-(SP)
_PMBackColor
BRA.S goHome
;---------------------------------------------------
;
; PROCEDURE ReleaseList(selection:ReqListRec); AAA2/18;
;
; Have the palette manager release any entries in the ReqListRec.
; This is a pointer to a list of device indices in the same format
; as is passed to RestoreEntries. RestoreEntries should call this
; routine when passed NIL for the color table.
;
; Preserves standard toolbox regs: D3-D7/A2-A4
;
ReleaseList PROC EXPORT
TST.L PMgrHandle
BEQ.S @Nothing ; No PMgr, do nothing.
MOVEM.L D3/D4/A2,-(SP) ; save regs, stack down 12
MOVE.L 16(SP),A2 ; A2->list of entries
MOVE.L PMgrHandle,A0
MOVE.L (A0),A0
MOVE nDevs(A0),D0 ; D0 = number PMgr known devs
LEA DevHandles(A0),A0 ; A0->list of PMgr known devs
CLR D3
MOVE.L theGDevice,D1
@findDev CMP.L DevHandle(A0,D3*8),D1 ; Is it this device?
BEQ.S @foundDev ; Yes => go zap some links.
ADDQ #1,D3
CMP D0,D3
BLO @findDev
BRA.S @GoHome ; Ran out of devices
@foundDev LSL #8,D3 ; Get device in higher bits
MOVE (A2)+,D4 ; D4=number of indices to clear
@zapLoop MOVE (A2)+,D0
MOVE.B D0,D3
MOVE D3,-(SP) ; Push device/index combo
_ZapLinks
DBRA D4,@zapLoop
@goHome MOVEM.L (SP)+,D3/D4/A2
@Nothing RTD #4
;---------------------------------------------------
;
;FUNCTION FindModeID(gd:GDHandle; depth: INTEGER):INTEGER;
;
; return the mode number (128-133 or so) for
; the requested depth on device "gd,"
; or zero if no such mode available.
; (internal routine for SetDepth and HasDepth
;
FindModeID FUNC Export
WITH SpBlock,VPBlock
FMVars RECORD {A6Link},Decrement
result DS.B 2 ; integer result
gd DS.B 4 ; input: GDevice
depth DS.B 2 ; input: depth
return DS.B 4 ; return address
A6Link DS.B 4 ; link
spBlk DS.B spBlockSize ; slot parameter block
vpPtr DS.B 4 ; pointer to vidParams block
linkSize DS.B 0 ; size of record
ENDR
WITH FMVars
LINK A6,#linkSize
MOVEM.L A2/D3,-(SP) ; save 'em
CLR result(A6) ; default to failure!
MOVE.L gd(A6),A0 ; A0 = gDevice handle
MOVE.L (A0),A1 ; A1->gDevice
MOVE.L UTableBase,A0 ; A0->unit table
MOVE gdRefNum(A1),D0 ; D0 = refnum
NEG D0
SUBQ #1,D0
MOVE.L (A0,D0.W*4),A1 ; A1 = AuxDCEHandle for gDevice
MOVE.L (A1),A1 ; A1 = AuxDCEPtr for gDevice
LEA spBlk(A6),A0 ; A0 -> spBlock
MOVE.B dCtlSlot(A1),spSlot(A0) ; stash gDevice slot
CLR.B spID(A0) ; clear the ID
MOVE #catDisplay,spCategory(A0) ; category: display
MOVE #typVideo,spCType(A0)
MOVE #drSwApple,spDrvrSW(A0) ; Apple™ style driver
MOVE.B #1,spTBMask(A0)
_sNextTypeSRsrc
BNE.S @goHome ; failure
MOVE.L spsPointer(A0),A2 ; keep saving it here
MOVE #127,D3 ; the 0th mode we'll look for
@depthScan
ADDQ #1,D3 ; bump to next mode
MOVE.B D3,spID(A0) ; look for the next mode
MOVE.L A2,spsPointer(A0) ; sFindStruct wipes out each time
_sFindStruct ; look for it
BNE.S @goHome ; failure
MOVE.B #mVidParams,spID(A0) ; now we look for video params
_sGetBlock
BNE.S @goHome ; failure
MOVE.L spResult(A0),A1 ; A1->vidParam block, finally
MOVE vpPixelSize(A1),D0 ; D0 = depth for this description
CMP depth(A6),D0 ; the one we want?
BNE.S @depthScan ; scan 'til found, or slot error
MOVE D3,result(A6)
@goHome MOVEM.L (SP)+,A2/D3
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
;FUNCTION SetDepth(gd:GDHandle; depth: INTEGER; whichFlags:SHORT; flags:SHORT):OSErr; AAA2/19
;
;
SetDepth FUNC EXPORT
whichMask EQU $00FF ; only allow user to change low byte of gdFlags
SDVars RECORD {A6Link},DECREMENT
result DS.B 2 ; boolean result
gd DS.B 4 ; input: GDevice to set
depth DS.B 2 ; input: depth to set to
whichFlags DS.B 2 ; which GDFlags to affect
flags DS.B 2 ; input: various flags
return DS.B 4 ; return address on stack
A6Link DS.B 4 ; link
r DS.B 4 ; regionhandle
oldPort DS.B 4 ; previous port
myRect DS.B 8 ; rectangle for little black corners
linkSize DS.B 0 ; size of record
ENDR
WITH SDVars
LINK A6,#linkSize
2020-05-10 05:37:38 +00:00
MOVEM.L A2/D3-D5,-(SP) ; <6>
2019-07-27 14:37:48 +00:00
MOVE #paramErr,result(A6) ; default to failure!
MOVE.L gd(A6),A0 ; A0 = gDevice handle
MOVE.L (A0),A1 ; A1->gDevice
MOVE whichFlags(A6),D0 ; D0 = mask of flags to change
ANDI #whichMask,D0 ; D0 = only the ones we let them change
MOVE D0,D1 ; D1 = mask of flags to change
AND flags(A6),D1 ; D1 = only the flags to change
NOT D0 ; D0 = mask of flags to keep
AND gdFlags(A1),D0 ; D0 = all the unchanged gdFlags
OR D1,D0 ; D0 = new gdFlags word
MOVE D0,gdFlags(A1) ; Put back into gDevice
MOVE gdRefNum(A1),D3 ; D3 = refnum, for later use
MOVE depth(A6),D4 ; get the depth or mode
TST.B D4 ; see which it is
BMI.S @gotMode
SUBQ #2,SP
MOVE.L gd(A6),-(SP)
MOVE D4,-(SP)
Import FindModeID
BSR FindModeID ; find the mode number, if it exists
MOVE (SP)+,D4 ; did we find one?
BEQ @goHome
2020-05-10 05:37:38 +00:00
@gotMode Move.w theMenu,D5 ; Get the currently hilited menuID.
2019-07-27 14:37:48 +00:00
Clr.w -(Sp) ; And unhilite it.
_HiliteMenu
@NotMain1
; Originally, DVB wasnt getting the current port until corner-rounding code
; was about to be executed (below). That seemed to cause port problems, so
; I move the port getting/setting code to here (which is the way Monitors
; does it).
;
; -- jmp --
PEA oldPort(A6) ; Save the current port
_GetPort
MOVE.L WMgrPort,-(SP) ; We want to use the WMgrPort
_SetPort
MOVE D3,-(SP) ; push refnum
EXT.L D4
MOVE.L D4,-(SP) ; push new gdev mode
MOVE.L gd(A6),-(SP) ; push the handle
_InitGDevice
Move.w D5,-(Sp) ; Get the hilite state.
_HiliteMenu ; Restore it.
CLR.L -(SP) ; Activate the front palette
_FrontWindow ; before drawing anything.
_ActivatePalette
; In Monitors (the cdev) this is the point in the code where
; the PortList is walked to update all the CGrafPorts to the
; new depth. We dont need to do that here because InitGDevice
; does that for us with Save/ResoreFore and Save/RestoreBack
; calls.
;
; -- jmp --
; If the LayerManger is around, we need to start at the root, otherwise
; we just use FrontWindow. Originally, DVB had PaintOne instead of
; PaintBehind here but VL said that was wrong. Also, Monitors uses the
; PaintOne/PaintBehind method instead of PaintOne/PaintOne method.
;
; -- jmp --
If HasLayers Then
_RedrawAll ; CheckUpdate on all layers <42>
Else
SUBQ #4,SP
_NewRgn
MOVE.L (SP),r(A6) ; get a fresh region, LEAVE ON STACK
MOVE.L gd(A6),A0 ; A0 = gd handle
MOVE.L (A0),A0 ; A0->gdevice
PEA gdRect(A0) ; push rectangle to RectRgn
_RectRgn ; r is now our region
CLR.L -(SP)
MOVE.L r(A6),-(SP)
_PaintOne
SUBQ #4,SP
_FrontWindow
MOVE.L r(A6),-(SP)
_PaintBehind
MOVE.L r(A6),-(SP) ; Done with region
_DisposRgn
Endif
CLR.L myRect+topLeft(A6) ; Set the empty rect
CLR.L myRect+botRight(A6)
MOVE.L deviceList,A2 ; A2 = 1st GDHandle
@dloop MOVE.L (A2),A2 ; A2 -> GDevice
BTST #screenActive,gdFlags(A2) ; bit 15 in upper byte of word
BEQ.S @dloopEnd ; Inactive screen?
PEA gdRect(A2)
PEA myRect(A6)
MOVE.L (SP),-(SP)
_UnionRect
@dloopEnd MOVE.L gdNextGD(A2),A2
MOVE.L A2,D0
BNE.S @dloop
PEA myRect(A6) ; Set a nice big clip
_ClipRect
PEA myRect(A6)
MOVE.L #$FFFDFFFD,-(SP) ; outset by three
_InsetRect
MOVE.L #$00030003,-(SP) ; pensize is three
_PenSize
PEA myRect(A6)
MOVE.L #$00160016,-(SP) ; and a radius for nice rounding
_FrameRoundRect ; and black out the corners
_PenNormal
MOVE.L oldPort(A6),-(SP) ; restore the previous port
_SetPort
MOVE.L gd(A6),A0
MOVE.L (A0),A0
BTST #mainScreen,gdFlags(A0) ; (mainScreen=11, in upper byte)
BEQ.S @notMain
_DrawMenuBar
@notMain
CLR result(A6) ; success
@goHome
MOVEM.L (SP)+,A2/D3-D5
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
;FUNCTION HasDepth(gd:GDHandle; depth: INTEGER; whichFlags:SHORT; flags:SHORT):BOOLEAN;
;
;
HasDepth FUNC EXPORT
whichMask EQU $FFFE ; the lowest bit is settable, else fail
SDVars RECORD {A6Link},DECREMENT
result DS.B 2 ; boolean result
gd DS.B 4 ; input: GDevice to set
depth DS.B 2 ; input: depth to set to
whichFlags DS.B 2 ; which GDFlags to affect
flags DS.B 2 ; input: various flags
return DS.B 4 ; return address on stack
A6Link DS.B 4 ; link
linkSize DS.B 0 ; size of record
ENDR
WITH SDVars
LINK A6,#linkSize
CLR result(A6) ; default to failure!
MOVE whichFlags(A6),D0 ; D0 = mask of flags to change
AND flags(A6),D0 ; D0 = new flags to set
AND #whichMask,D0 ; D0 = all the bits we can't change
BNE.S @goHome ; User tried to set bits we don't yet do!
SUBQ #2,SP
MOVE.L gd(A6),-(SP)
MOVE depth(A6),-(SP)
BSR FindModeID ; find the mode number, if it exists
MOVE (SP)+,result(A6) ; did we find one?
@goHome
UNLK A6
RTD #result-return-4
;---------------------------------------------------
;
;FUNCTION PMgrVersion:INTEGER; AAA2/21;
;
;
PMgrVersion FUNC EXPORT
MOVE #PMgrVersNum,4(SP) ; stash it above the return address
CLR D0 ; no error
RTS
;---------------------------------------------------
;
;PROCEDURE SetPaletteUpdates(PaletteHandle, Integer); AAA2/22;
;
; Set the type of color updates that this palette will receive,
; from the xxxPaletteUpdates constants.
;
; (We don't check for nil being passed; it must be a real palette).
SetPaletteUpdates PROC EXPORT
SPUVars RECORD {A6Link},DECREMENT
result DS.B 0 ; no result
srcPalette DS.B 4 ; input: Palette to set
updateMode DS.B 2 ; input: new update level
return DS.B 4 ; return address on stack
A6Link DS.B 4 ; link
linkSize DS.B 0 ; size of record
ENDR
WITH SPUVars
LINK A6,#linkSize
MOVE.L srcPalette(A6),A0
MOVE.L (A0),A0 ; A0->palette
MOVE updateMode(A6),D0
LSL #8,D0 ; Move those two bits high
LSL #6,D0 ; Move those two bits high
AND #$C000,D0
MOVE pmPrivate(A0),D1
AND #$3FFF,D1
OR D0,D1
MOVE D1,pmPrivate(A0)
UNLK A6
CLR.L D0 ; No error
RTD #result-return-4
;---------------------------------------------------
;
;FUNCTION GetPaletteUpdates(PaletteHandle, Integer):INTEGER; AAA2/23;
;
; inverse of SetPaletteUpdates
;
GetPaletteUpdates PROC EXPORT
GPUVars RECORD {A6Link},DECREMENT
result DS.B 2 ; result: update level
srcPalette DS.B 4 ; input: Palette to look at
return DS.B 4 ; return address on stack
A6Link DS.B 4 ; link
linkSize DS.B 0 ; size of record
ENDR
WITH GPUVars
LINK A6,#linkSize
MOVE.L srcPalette(A6),A0
MOVE.L (A0),A0
MOVE pmPrivate(A0),D0
LSR #8,D0
LSR #6,D0
MOVE D0,result(A6)
UNLK A6
CLR.L D0
RTD #result-return-4
;---------------------------------------------------
;
; FUNCTION GetGray(device: GDHandle, backGround: RGBColor;
; VAR foreGround: RGBColor): BOOLEAN; AAA2/25;
;
GetGray PROC EXPORT
GGVars RECORD {A6Link},DECREMENT
result DS.B 2 ; result: BOOLEAN
device DS.B 4 ; device to check
bGround DS.B 4 ; input: backGound Color
fGround DS.B 4 ; variable parameter foreGround Color
return DS.B 4 ; return address on stack
A6Link DS.B 4 ; link
oldGD DS.B 4 ; GDevice before we started
realFore DS.B 6 ; actual RGBValue of foreGround
realBack DS.B 6 ; actual RGBValue of backGround
calcAvg DS.B 6 ; calculated average
realAvg DS.B 6 ; real average
linkSize DS.B 0 ; size of record
ENDR
WITH GGVars
LINK A6,#linkSize
MOVE.L A2, -(SP)
CLR.B result(A6) ; Assume false
MOVE.L TheGDevice, oldGD(A6)
TST.L device(A6)
BEQ.S @theDeviceSet
MOVE.L device(A6), TheGDevice
@theDeviceSet
SUBQ #4, SP
MOVE.L bGround(A6), -(SP)
_Color2Index
PEA realBack(A6)
_Index2Color
SUBQ #4, SP
MOVE.L fGround(A6), -(SP)
_Color2Index
PEA realFore(A6)
_Index2Color
LEA realFore(A6), A0
LEA realBack(A6), A1
LEA calcAvg(A6), A2
MOVEQ #2, D1
@addLoop MOVE.W (A0)+, D0
ADD.W (A1)+, D0
ROXR #1, D0
BMI.S @lighterThanHalf
ADDQ #2, D0
@lighterThanHalf
MOVE.W D0, (A2)+
DBRA D1, @addLoop
SUBQ #4, SP
PEA calcAvg(A6)
_Color2Index
PEA realAvg(A6)
_Index2Color
MOVE.L oldGD(A6), TheGDevice
SUBQ #2,SP
PEA realFore(A6)
PEA realAvg(A6)
JSR DeltaRGB
SUBQ #2,SP
PEA realBack(A6)
PEA realAvg(A6)
JSR DeltaRGB
SUBQ #2,SP
PEA calcAvg(A6)
PEA realAvg(A6)
JSR DeltaRGB
MOVE (SP)+,D0 ; D0 = delta to self
MOVE (SP)+,D1 ; D1 = delta to back
MOVE (SP)+,D2 ; D2 = delta to fore
LSR #1,D1 ; bias to prefer pattern
LSR #1,D2 ; unless there's a good match
CMP D1,D0 ; Are we closer to back?
BHS.S @twoColor ; yes => dither
CMP D2,D0 ; Are we closer to fore?
BHS.S @twoColor ; yes => dither
MOVE.B #1, result(A6) ; return true
MOVE.L fGround(A6), A0
LEA realAvg(A6), A1
MOVE.L (A1)+, (A0)+
MOVE.W (A1)+, (A0)+
@twoColor MOVE.L (SP)+, A2
UNLK A6
CLR.L D0
RTD #result-return-4
ENDPROC
;---------------------------------------------------
;
; FUNCTION CheckColors(device:GDHandle,colors:CTabHandle;
; maxTolerance,maxAveTolerance:INTEGER):BOOLEAN; AAA2/24;
;
; See if the list of color specified can be displayed nicely on
; theGDevice.
CheckColors PROC EXPORT
CCVars RECORD {A6Link},DECREMENT
result DS.B 2 ; result: BOOLEAN
device DS.B 4 ; device to check
colors DS.B 4 ; input: color list to check
maxTol DS.B 2 ; maximum tolerance for each color
maxAveTol DS.B 2 ; maximum average tolerance
return DS.B 4 ; return address on stack
A6Link DS.B 4 ; link
oldGD DS.B 4 ; GDevice before we started
;colorCount DS.B 2 ; ctSize+1
aColor DS.B 6 ; scratch rgb
bColor DS.B 6 ; another scratch rgb
hState DS.B 2 ; handle state of clut
linkSize DS.B 0 ; size of record
ENDR
WITH CCVars
LINK A6,#linkSize
MOVEM.L A2-A3/D3-D7,-(SP)
MOVE.L TheGDevice,oldGD(A6)
MOVE.L device(A6),D0 ; did the user specify a GDevice?
BEQ.S @noDevice
MOVE.L D0,TheGDevice
@noDevice
MOVE.B #1,result(A6) ; Assume True
MOVEA.L TheGDevice, A0 ; get a handle to TheGDevice
MOVEA.L (A0), A0 ; dereference the Handle
CMPI.W #$2, gdType(A0) ; check if the device is direct (16 or 32 bits)
BEQ.S @exit
MOVEA.L gdPMap(A0), A0 ; Get the PixMapHandle
MOVEA.L (A0), A0 ; Get the PixMapPtr
MOVEA.L pmTable(A0), A0 ; Get the PixMap CTabHandle
MOVEA.L (A0), A0 ; Get the CTabPtr
MOVE.L ctSeed(A0), D0 ; Get the Seed
MOVEQ #(8+32), D1 ; check for 8-bit grey-scale
CMP.L D0, D1
BEQ.S @exit
MOVE.L colors(A6), A0 ; Get the input color table handle
MOVE.L (A0), A0 ; dereference
MOVE.L ctSeed(A0), D1 ; get the Seed
CMP.L D0, D1 ; check if seeds are identical
BEQ.S @exit
MOVEQ #(4+32), D1 ; check for 4-bit gray-scale destination
CMP.L D0, D1
BEQ.S @exit
; MOVE.W ctSize(A0), D1 ; our device clut is four-bit gray-scale and we're checking that the source clut is four-bits or less
; CMPI.W #15, D1
; BLS.S @exit
;@doneChecking
CLR result(A6) ; default to "false" = failure
CLR.L D7 ; D7 = total color deltas
MOVE.L colors(A6), A0
_HGetState ; A0 already contains the handle to the ColorTable
MOVE D0,hState(A6) ; D6 = previous colors memstate
_HLock
MOVE.L (A0),A2 ; A2->color table to check
MOVE ctSize(A2),D3 ; D3 = last color in table
MOVEQ #0, D5 ; initialized number of colors checked
; MOVE D3,D0
; ADDQ #1,D0
; MOVE D0,colorCount(A6) ; save count of colors
; MOVEQ #-1, D6 ; set D6 to impossible value for index check.
ADDQ #8,A2 ; A2->1st color in table
@loop
MOVEQ #4, D0 ; set bit 2 in D0
AND.W (A2), D0 ; test inhibit bit in value field of colorSpec
BNE.S @next ; skip this color if the bit is set
ADDQ.L #1, D5; ; increment number of colors checked
BSR.S @color2color ; Get D5=index, D0=delta, D7 = ∑deltas
; CMP.L D6,D5 ; Does it match the last one?
; BEQ.S @gohome ; Yes=>unacceptable
CMP maxTol(A6),D0 ; Are we within maximum tolerance?
BHI.S @goHome ; No=>fail
; MOVE.L D5,D6 ; get last index here
@next ADDQ #8,A2 ; Bump to next color
DBRA D3,@loop ; loop through all colors
DIVU D5,D7 ; compute average tolerance
; DIVU colorCount(A6),D7 ; compute average tolerance
CMP maxAveTol(A6),D7 ; in range?
BHI.S @goHome ; No=>don't set result true
MOVE.B #1,result(A6) ; We made it through all the colors
@gohome
MOVE.L colors(A6),A0
MOVE hState(A6),D0 ; old handle state
_HSetState
@exit
MOVE.L oldGD(A6),TheGDevice ; restore gdevice
MOVEM.L (SP)+,A2-A3/D3-D7
UNLK A6
CLR.L D0
RTD #result-return-4
@color2color
;convert rgb A2+2 to index in D5, and back to color, delta in D0
SUBQ #4,SP ; space for result
PEA 2(A2)
_Color2Index
; MOVE.L (SP),D5 ; get color's index in D5
PEA aColor(A6) ; place to get actual color
_Index2Color
SUBQ #2,SP
PEA aColor(A6)
PEA 2(A2)
JSR DeltaRGB
CLR.L D0
MOVE (SP)+,D0 ; Get delta into D0
ADD.L D0,D7 ; Sum the delta into D7
RTS
;---------------------------------------------------
;
; PROCEDURE PMgrDispatch(selector:INTEGER); AAA2;
;
; Here, we divvy up our last trap amongst a whole bunch of functions, using D0
; as a selector. All registers preserved during dispatch except D0.
PROC
EXPORT PMgrDispatch
procTable
switch00 DC Entry2Index-procTable ; public choices
switch01 DC Index2Entries-procTable
switch02 DC RestoreDeviceClut-procTable
switch03 DC ResizePalette-procTable
switch04 DC ZapLinks-procTable
switch05 DC WhatPal-procTable
switch06 DC PMgrFinalError-procTable
switch07 DC PMgrFinalError-procTable
switch08 DC PMgrFinalError-procTable
switch09 DC PMgrFinalError-procTable
switch10 DC DeltaRGB-procTable ; secret choices
switch11 DC NewHiliteColor-procTable
switch12 DC PMgrExit-procTable
switch13 DC SaveFore-procTable
switch14 DC SaveBack-procTable
switch15 DC RestoreFore-procTable
switch16 DC RestoreBack-procTable
switch17 DC PMgrFinalError-procTable
switch18 DC ReleaseList-procTable
switch19 DC SetDepth-procTable
switch20 DC HasDepth-procTable
switch21 DC PMgrVersion-procTable
switch22 DC SetPaletteUpdates-procTable
switch23 DC GetPaletteUpdates-procTable
switch24 DC CheckColors-procTable
switch25 DC GetGray-procTable
switchMax EQU (*-procTable)/2
; Say, don't forget that each pmgr dispatch must set D0 to zero on return!
PMgrDispatch
CMP.B #switchMax,D0 ; Is this (yet) a real function?
BHS.S PMgrFinalError ; No! Bye!
MOVE.L A0,-(SP) ; preserve A0
LEA procTable,A0 ; A0->list of proc pointers
AND #$00FF,D0 ; Only use low byte for offset
MOVE (A0,D0*2),D0 ; Get offset to the one we want
ADDA D0,A0 ; Add offset
MOVE.L A0,-(SP) ; Push target as return address
MOVE.L 4(SP),A0 ; Restore A0
RTD #4 ; Go there. Straight.
PMgrFinalError
LSR #8,D0 ; Get to high byte of D0: arg count
MOVE.L (SP)+,A0 ; Pop return address
ADD D0,SP ; Remove those args
MOVEQ #-1,D0 ; Error condition
JMP (A0) ; bye.
ENDPROC
;---------------------------------------------------
; Thus ends the PaletteManager - ah, a sad thing it is, to be done. But WAIT! There's
; MORE! Let's patch RGBFORECOLOR and RGBBACKCOLOR just for grins! Yeah!
IF NOT ROMPaletteMgr THEN ; no patches for the ROM version RWH.C864
IF NOT JacksonPollack THEN ; (skip RGBFore/Back, since JP knows it)
;---------------------------------------------------
;
; procedure RGBForeColor (Color : RGBColor);
;
; This routine takes an RGB triple and sets the current Graf- or CGrafPort
; fields so that drawing will take place with the best match of the
; requested color, using the current GDevice's color matching rules. The
; appropriate fields are set depending on portType
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBForeColor) (RGBForeColor)
RGBForeColor PROC EXPORT
EXPORT RGBBackColor,RGB2OLD
StdDevCall Equ $1D2A0 ; RGBForeColor; RGBBackColor is $4081D2B0 <PB302>
StdDevMask Equ $FFFFFFEF ; the calls are different only at bit 4!
MOVEQ #FGCOLOR,D0 ; get offset to index field
MOVEQ #RGBFgColor,D1 ; get offset to RGB field
SHARE MOVE.L 4(SP),A1 ; point at the RGB color
MOVE.L GRAFGLOBALS(A5),A0 ; get the QuickDraw globals pointer
MOVE.L THEPORT(A0),A0 ; point at the port
PEA 0(A0,D0) ; save pointer to the index field
TST PORTBITS+ROWBYTES(A0) ; is it a new port?
BMI.S NEWPORT ; => yes, set RGB components
JSR RGB2OLD ; else convert RGB to old color
BRA DONE ; =>
; To keep the stack correct we will momentarily preempt A1. We can restore it in a bit.
; Also, since we no longer need the offset to the index field
NewPort Move.L GrafVars(A0),A1 ; get the GrafVars handle
CmpA.L #Nil,A1 ; is it nil?
Beq.S PuntPmCalls ; yes => punt and do the normal call
Move.L (A1),A1 ; dereference it into A1
Move.L 4(SP),D2 ; get the return address
Sub.l ROMBase, D2 ; Make it offset within ROM, <PB302>
And.L #StdDevMask,D2 ; and it with the std mask
Cmp.L #StdDevCall,D2 ; is it from StdDevLoop?
Bne.S NormalCall ; no => make the normal call
Tst.L PmFgColor(A1) ; is there a palette? EHB.PBnnn
Bne.S FoundAPltt ; yes => we can do it AWC.PB508
Tst.L AppPalette ; is there an AppPalette? AWC.PB508
Beq.S NormalCall ; => no, do normal call EHB.PBnnn
FoundAPltt Move PmFlags(A1),D2 ; get the Palette Manager flags AWC.PB508
Cmp #FgColor,D0 ; was it forecolor?
Bne.S GetBack ; no => get back color flag
BTst #PmFgBit,D2 ; did PmForeColor set up this port?
Beq.S PuntPmCalls ; no => continue normally
AddQ #4,SP ; we won't need the pointer to the index
Move pmFgIndex(A1),-(SP) ; push the entry number
_PmForeColor ; set the port using PmForeColor
Bra.S GoHome ; all finished
GetBack BTst #PmBkBit,D2 ; did PmBackColor set up this port?
Beq.S PuntPmCalls ; no => continue normally
AddQ #4,SP ; we won't need the pointer to the index
Move pmBkIndex(A1),-(SP) ; push the entry number
_PmBackColor ; set the port using PmBackColor
Bra.S GoHome ; all through
NormalCall Move PmFlags(A1),D2 ; get flags
Cmp #FgColor,D0 ; is this a foreground call?
Bne.S NotFgCall ; no => clear PmBkBit
BClr #PmFgBit,D2 ; clear the foreground flag bit
Bra.S CommonFlags ; reunite it
NotFgCall BClr #PmBkBit,D2 ; clear the background flag bit
CommonFlags Move D2,PmFlags(A1) ; save the flags to GrafVars
PuntPmCalls Move.L 8(SP),A1 ; restore the pointer to the RGBColor
; Here is the normal RGBForeColor code code
MOVE.L red(A1),red(A0,D1) ; copy red and green components to the port
MOVE.W blue(A1),blue(A0,D1) ; and blue too
; make an rgbColor on the stack
MOVE.L green(A1),-(SP) ; copy green and blue
MOVE.W red(A1),-(SP) ; copy red
SUBQ #4,SP ; make room for function return
PEA 4(SP) ; push pointer to rgb
_Color2Index ; convert it to an index
MOVE.L (SP)+,D0 ; get the index result
ADDQ #6,SP ; get rid of the rgbColor
Done MOVE.L (SP)+,A0 ; get pointer to index field
MOVE.L D0,(A0) ; and set the index field
GoHome Rtd #4 ; all done
RGB2OLD
;-----------------------------------------------
;
; UTILITY TO CONVERT AN RGB (POINTED TO BY A1) VALUE
; TO AN OLD STYLE COLOR VALUE. RETURNS VALUE IN D0. CLOBBERS A0,D1
;
; USES HIGH BIT OF EACH COMPONENT TO SELECT RGB OFF (0) OR ON (1)
MOVEQ #0,D1 ; clear out D1
MOVE (A1)+,D1 ; get red
ADD.L D1,D1 ; get high bit
MOVE (A1)+,D1 ; get green
ADD.L D1,D1 ; get high bit
MOVE (A1)+,D1 ; get blue
ADD.L D1,D1 ; get high bit
SWAP D1 ; get RGB index
noBlue LEA MapTbl,A0 ; get translate table
MOVEQ #0,D0 ; clear out high word
MOVE 0(A0,D1*2),D0 ; convert to planar value
RTS ; => all done
; TABLE TO MAP FROM 3 BIT RGB TO OLD-STYLE COLOR INDICES
MapTBL DC.W blackColor ; RBG = 0,0,0 -> black
DC.W blueColor ; RBG = 0,0,1 -> blue
DC.W greenColor ; RBG = 0,1,0 -> green
DC.W cyanColor ; RBG = 0,1,1 -> cyan
DC.W redColor ; RBG = 1,0,0 -> red
DC.W magentaColor ; RBG = 1,0,1 -> magenta
DC.W yellowColor ; RBG = 1,1,0 -> yellow
DC.W whiteColor ; RBG = 1,1,1 -> white
;---------------------------------------------------
;
; procedure RGBBackColor (Color : RGBColor);
;
; This routine takes an RGB triple and sets the current Graf- or CGrafPort
; fields so that drawing will take place with the best match of the
; requested color, using the current GDevice's color matching rules. The
; appropriate fields are set depending on portType.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBBackColor) (RGBBackColor)
RGBBackColor
MOVEQ #BKCOLOR,D0 ; get offset to the index field
MOVEQ #RGBBkColor,D1 ; get offset to RGB field
BRA SHARE ; => and use common code
ENDIF ;(Jackson Pollack)
IF PatchGetCTable THEN
;(This GetCTable was copied out of ColorMgr.a, and is used for patching
; when we install the new palette manager without 32-bit quickdraw.)
;---------------------------------------------------
;
; FUNCTION myGetCTable(ID:INTEGER):Handle;
;
; Get a 'clut' resource of the specified ID, as a non-resource
; handle. Unless, of course, the number is 32+[1,2,4,8] in which
; case we return a gray scale of that size. Or if the number is
; 64+[1,2,4,8] we'll return a clut with a hilite modification.
;
; Passing 64 plus other than 1, 2, 4, or 8 will yield strange results.
;
; stack like this: (SP) return.L, 4(SP) depth.W, 6(SP) result handle.L
;
; <dvb8> for whole routine
PROC
EXPORT MyGetCTable
GrayMuls DC.W $FFFF,$5555,$0000,$1111,$0000,$0000,$0000,$0101 ; <BAL 06Jun89>
; gray multiplier 1-bit 2-bit 4-bit 8-bit
doGrayClut AND #$F,D0 ; Mask the graybit
MOVE D0,4(SP) ; Put it in the passed param
CLR.L D1
ADDQ #3,D0 ; + 3 becomes * 8 on next line, for c-Spec size
BSET D0,D1 ; 2 to the nth
ADDQ.L #8,D1 ; Add size of ctab header
MOVE.L D1,D0 ; Here, for newhandle
_NewHandle ; Get a brand new colortable
BEQ.S @gotGrayH ; Did we?
CLR.L 6(SP) ; No=>return nil
RTD #2
@gotGrayH MOVE 4(SP),D0 ; Get depth again
LEA GrayMuls-2,A1 ; A1->our gray multiplier table <2.1>
MOVE.w (A1,D0*2),D1 ; D1.w = color step for this bit depth <BAL 06Jun89>
move.w d1,d2 ; copy into d2 <BAL 06Jun89>
swap d2 ; set up high word <BAL 06Jun89>
move.w d1,d2 ; replicate throughout long <BAL 06Jun89>
MOVE.L (A0),A1 ; A1->our brand new ctable clut
move.w #$8000,transIndex(A1) ; mark as device clut
CLR D1 ; From bit depth,
BSET D0,D1 ; Generate number of entries
SUBQ #1,D1 ; Minus one, for ctSize silliness
MOVE D1,ctSize(A1) ; Set size of colortable
CMPI #3,D0 ; Size 1 or 2 bits? <dvb>
BLT.S @graySeed ; Yes => don't call it GrayScale by seed <dvb>
ADD #32,D0 ; Constant +32 for GrayScale seeds
@graySeed MOVE.L D0,ctSeed(A1) ; Jam seed <dvb>
LEA ctTable(A1),A1 ; A1->first colorSpec
MOVEQ #-1,D0 ; Lowest index is white
MOVEQ #0,D1 ; D1 will be .value fields <dvb>
@grayLoop MOVE D1,(A1)+ ; put pixel value in .value field <dvb>
ADDQ #1,D1 ; <dvb>
MOVE.L D0,(A1)+ ; Stash red and green
MOVE D0,(A1)+ ; Stash blue, A1->next cSpec
SUB.L D2,D0 ; Bump D0 to next reasonable value
BCC.S @grayLoop ; Until we go under zero, beyond black
BRA GoHome
doHiliteClut AND #$F,D0 ; Mask the hilitebit
MOVE D0,-(SP) ; Push it for the Resource read
BSR ReadIt ; Okay, read it.
MOVE.L A0,D0 ; A good thing?
BEQ GoHome ; No=>go home (with NIL from A0)
MOVE.L (A0),A1 ; A1->color table
SUBQ #4,SP ; Space for new seed
_GetCTSeed ; Get that new seed
MOVE.L (SP)+,ctSeed(A1) ; Put seed into synthetic table
MOVE 4(SP),D0 ; D0 = clutID again
BTST #1,D0 ; Two bit mode?
BEQ.S checkFour ; No=>check other stuff
; If the hilite color is a gray then CLUT is OK <2.2>
LEA HiliteRGB,A1 ; Point at hilite color <2.2>
MOVE.B red(A1),D1 ; Get red msb <2.2>
CMP.B green(A1),D1 ; green same as red? <2.2>
BNE.S @notGray ; no, go use it. <2.2>
CMP.B blue(A1),D1 ; blue same as red and green? <2.2>
BEQ GoHome ; yes, leave clut alone. <2.2>
@notGray MOVE.L (A0),A1 ; A1->color table <2.2>
LEA ctTable+8+rgb(A1),A1 ; Bump A1 to 2nd entry.rgb.red
MOVE.L #$7FFF7FFF,(A1)+ ; Put 50% gray into red,green
MOVE #$7FFF,(A1)+ ; and blue
ADDQ #2,A1 ; Bump past .value field in third entry
MOVE.L HiliteRGB,(A1)+ ; Put hilite color into red,green
MOVE HiliteRGB+blue,(A1) ; and blue.
BRA GoHome
checkFour BTST #2,D0 ; Four bit mode?
BEQ GoHome ; No => must be 1 or 8-bit, so we're done.
MOVE #14,D2 ; DBRA counter, skipping white
MOVE.L #$0001FFFF,D1 ; Lo word = error distance, Hi word = best index
@B4loop SUBQ #2,SP ; space for result
PEA HiliteRGB ; push system hilite color
PEA ctTable+rgb(A1,D2*8) ; push color we're checking
JSR DeltaRGB
MOVE (SP)+,D0
CMP D0,D1
BLS.S @B4loopEnd
MOVE D0,D1 ; Get new smallest delta
SWAP D1 ; D1 = Get index number in low word
MOVE D2,D1 ; Get new closest index
SWAP D1 ; D1 = Put delta back to low word
@B4loopEnd SUBQ #1,D2
BNE.S @B4loop ; Loop on down, but skip zero
CMPI #$3000,D1 ; Are we pretty darned tolerant?
BLS.S GoHome ; Yes=> we're fine, go home
SWAP D1
LEA ctTable+rgb+red(A1,D1*8),A1 ; A1->RGB to tweak
@realClose MOVE.L HiliteRGB+red,D0 ; D0 = hilite r,g
SWAP D0 ; D0.W = red
ADD red(A1),D0 ; D0.W = hilite red+old red
ROXR #1,D0 ; Average
MOVE D0,red(A1) ; write red
SWAP D0
ADD green(A1),D0 ; D0.W = hilite green+old green
ROXR #1,D0 ; Average
MOVE D0,green(A1) ; write green
MOVE HiliteRGB+blue,D0 ; D0.W = hilite blue
ADD blue(A1),D0
ROXR #1,D0 ; Average
MOVE D0,blue(A1) ; write blue
SUBQ #2,SP ; space for result
PEA HiliteRGB ; Have we really got the hilite
PEA (A1) ; color within a reasonable range?
JSR DeltaRGB ; Let's see.
CMPI #$3000,(SP)+ ; 3000 is good enough to look decent.
BHI.S @realClose ; But, its not there yet, so avg again.
BRA.S GoHome
myGetCTable MOVE 4(SP),-(SP) ; First, try to read a resource
BSR.S ReadIt ; (do that)
MOVE.L A0,D0 ; Get anything?
BEQ.S notRes ; No=>try other means
GoHome MOVE.L A0,6(SP) ; Yes=>stash it
RTD2 RTD #2 ; roger and out.
notRes MOVE 4(SP),D0 ; Get requested ID
CMPI #72,D0 ; 72 is the highest we can noodle
BHI.S RTD2
MOVE.L #$00000116,D1 ; Bits 1, 2, 4, and 8 are set
BTST D0,D1 ; Are low 5 bits in [1,2,4,8]?
BEQ.S RTD2
BTST #5,D0
BNE.S doGrayClut ; 32+[1,2,4,8]
BTST #6,D0
BNE.S doHiliteClut ; 64+[1,2,4,8]
BRA.S RTD2
readIt SUBQ #4,A7 ; space for result
MOVE.L #'clut',-(SP) ; resource type
MOVE 12(SP),-(SP) ; push ID number
_GetResource ; Get it.
MOVE.L (A7)+,D0 ; D0 = resource handle.
BEQ.S @tryROM ; (OR NOT!) maybe the ROM has it.
MOVE.L D0,-(SP) ; Push to save it, a moment.
MOVE.L D0,-(SP) ; Push to detach it
_DetachResource ; It's no longer a resource
MOVE.L (SP)+,A0 ; We'll return it in A0.
_HNoPurge ; make this non-purgeable (if it was) <16May89> DAF
MOVE.L (A0),A1 ; But first,
SUBQ #4,SP ; Number one,
_GetCTSeed ; Since we don't know where its been
MOVE.L (SP)+,(A1) ; A Fresh seed.
BRA.S @doneRead ; return, sans ID
@tryROM MOVE #-1,RomMapInsert ; This time, try 'da ROM
SUBQ #4,SP ; result
MOVE.L #'clut',-(SP) ; resource type
MOVE 12(SP),-(SP) ; resource ID
_GetResource ; Get it.
MOVE.L (A7)+,D0
BEQ.S @readFail ; It wasn't there! Not at all!
MOVE.L D0,A0 ; Put here for hand to hand
_HandToHand ; Make a normal handle from ROM resource
BEQ.S @doneRead ; Made it? If so, return, sans ID
@readFail SUBA.L A0,A0 ; A miserable failure.
@doneRead RTD #2 ; Lose ID, and go home.
ENDIF
IF PatchInitGDevice THEN
;=========================================================================================
;=========================================================================================
;
; Patch to InitGDevice. Add support for GDevices with baseAddrs that change across
; depths (Trident card) in a MultiFinder friendly way.
;
;=========================================================================================
;=========================================================================================
myInitGDevice PROC EXPORT
iiROMGetDevPixMap EQU $18FC0
WITH VDPageInfo ;<1.1>
;-------------------------------------------------------------
;
; PROCEDURE InitGDevice (refNum: INTEGER; mode: LONGINT; GDH: GDHandle);
;
; Initialize the specified device to the specified mode. The GDevice
; data is placed into the provided handle.
;
; If mode = -1 then the driver is not called. It is assumed that the pixmap
; has been set up before InitGDevice is called.
;
; CAUTION: this routine is used during ROM boot; various Macintosh functions
; may not yet be available! <dvb - found out the hard way>
;
IGDVars RECORD {A6Link},DECREMENT
result DS.B 0 ; no result
REFNUM DS.B 2
MODE DS.B 4 ; LONG, mode for video card
GDH DS.B 4 ; LONG, handle to devPort
return DS.B 4 ; the return address
A6Link DS.B 4 ; our link
IOPBlk DS.B IOVQElSize ; [64] parameter blk for I/O calls
VidParms DS.B 12 ; [12] size of mode params
GDHState DS.B 2 ; [word] lock state of GDH
GDPState DS.B 2 ; [word] lock state of GDP
SaveDevice DS.B 4 ; [long] saved device handle
oldBaseAddr DS.B 4 ; old base address, for later comparison
oldPort DS.B 4 ; thePort, before we got here
oldColor DS.B 8 ; a colorSpec used to reinstantiate fg/bk
VARSIZE DS.B 0 ; size of locals
ENDR
WITH IGDVars
LINK A6,#VARSIZE ; allocate stack frame
MOVEM.L D3/A2-A4,-(SP) ; save off work registers
MOVE.L GDH(A6),A0 ; get the gDevice handle
_HGetState ; get the current lock state
MOVE D0,GDHState(A6) ; save the state
_HLOCK ; and lock down the gDevice
MOVE.L (A0),A2 ; get pointer to gDevice record
MOVE.L GDPMap(A2),A0 ; get handle to pixMap
MOVE.L (A0),A1 ; A1->pixmap
MOVE.L baseAddr(A1),oldBaseAddr(A6) ; save the base address, for later portfixing
_HGetState ; get the current lock state of the pixmap
MOVE D0,GDPState(A6) ; save the state
_HLOCK ; lock it down
MOVE.L (A0),A3 ; keep pointer in A3
MOVE.L theGDevice,SaveDevice(A6) ; save theGDevice
TST.B QDExist ; qd around?
BNE.S @noShield ; no, don't shield cursor
BTST #screenDevice,gdFlags(A2) ; is it screen (check hi byte with #>8)
BEQ.S @noShield
PEA gdRect(A2)
CLR.L -(SP) ; in global coörds
_ShieldCursor
@noShield
; initialize the GDevice's mode and refnum
MOVE REFNUM(A6),GDRefNum(A2) ; set up RefNum
MOVE.L MODE(A6),D0 ; get the mode
CMP.L MinusOne,D0 ; is the mode -1?
BEQ ModeOK ; if so, then don't call the driver
; set up the driver parameter block in case we need to use it
LEA IOPBlk(A6),A0 ; point to parameter block
CLR.L ioCompletion(A0) ; no completion routine
CLR.W ioVRefNum(A0) ; no volRefNum
MOVE RefNum(A6),ioRefNum(A0) ; set device's refnum
LEA VidParms(A6),A1 ; point to params for GetMode
MOVE.L A1,csParam(A0) ; point to param list
CMP.L GDMode(A2),D0 ; has the mode changed?
BEQ GrayOrColor ; => no, so don't set depth
MOVE.L D0,GDMode(A2) ; set up mode
; setup the gDevice fields for the new screen depth
CLR GDCCDepth(A2) ; invalidate cursor depth <C837>
MOVEM.L A0/A1,-(SP) ; save these regs
MOVE REFNUM(A6),-(SP) ; push refnum
MOVE.L MODE(A6),-(SP) ; push mode
MOVE.L GDPMap(A2),-(SP) ; pixMap handle
PEA GDType(A2) ; point to device type
jsrROM iiROMGetDevPixMap ; read in pixMap from device
MOVEM.L (SP)+,A0/A1 ; restore them
; first, set the mode (A0 points to IOPB, A1 to control parameter block)
MOVE #2,csCode(A0) ; csc_GetMode
MOVE.L mode(A6),D0 ; get the mode
MOVE D0,csMode(A1) ; set desired mode
CLR csPage(A1) ; set page 1
CLR.L csData(A1) ; no additional data
_Control ,IMMED ; SetMode(Mode,Page,Data);
; then gray the screen
MOVE #5,csCode(A0) ; csc_GrayPage
_Control ,IMMED ; paint current page gray
; set the device to color or monochrome, according to GDFlags
GrayOrColor
MOVE GDFlags(A2),D0 ; get flags word
NOT D0 ; flip all bits
AND #1,D0 ; clear all but low bit
MOVE.B D0,csMode(A1) ; csMode = color/gray scale
MOVE #6,csCode(A0) ; csc_SetGray
_Control ,IMMED ; set color or monochrome
; if the device has a color table, set the device's color table
CMP #ClutType,GDType(A2) ; is there a lookup table?
BNE.S NoTbl ; =>no, don't set one
MOVE.L pmTable(A3),A0 ; get handle to color table
_HLock ; lock down the color table
;+++ LEA VidParms(A6),A1 ; point to params for SetEntries
MOVE.L (A0),A0 ; get ctabPtr <DAF>
CLR.W csStart(A1) ; start at zero, use sequence mode <DAF>
MOVE.W ctSize(A0),csCount(A1) ; for the length of the table <DAF>
LEA ctTable(A0),A0 ; get pointer to colorspecs <DAF>
MOVE.L A0,csTable(A1) ; color table pointer is first param <DAF>
LEA IOPBlk(A6),A0 ; point to parameter block
MOVE.W #3,csCode(A0) ; csc_SetEntries
MOVE.L A1,csParam(A0) ; move addr of parms into block
_Control ,IMMED ; SetEntries(ColorTable);
MOVE.L pmTable(A3),A0 ; get handle to color table
_HUnlock ; unlock the color table
NoTbl
; if CLUT or fixed color table, build inverse table
CMP #DirectType,GDType(A2) ; should there be an inverse table?
BEQ.S ModeOK ; =>no inverse table
MOVE.L pmTable(A3),-(SP) ; push color table handle
MOVE.L GDITable(A2),-(SP) ; push inverse table handle
MOVEQ #4,D0 ; make 4-4-4 inverse tables
MOVE D0,GDResPref(A2) ; save in GDevice
MOVE D0,-(SP) ; and push res
_MakeITable ; and generate table
; If this device has not been initialized from the system file, then copy the
; bounds from the pixMap to the GDRect. Otherwise copy the GDRect to the Bounds.
ModeOK
LEA BOUNDS(A3),A0 ; point to pixmap.bounds <C837>
LEA GDRECT(A2),A1 ; point to device's global rect
MOVE GDFlags(A2),D0 ; get the flags word
BTST #RAMInit,D0 ; initialized from RAM?
BEQ.S BndsOK ; => no, copy pixMap.bounds to GDRect
EXG A0,A1 ; else copy GDRect to pixMap.bounds
BndsOK MOVE.L (A0)+,(A1)+ ; copy topLeft
MOVE.L (A0)+,(A1)+ ; copy botRight
; <dvb 3Jan89>
; if we're about the main device, then fix all those
; potentially errant ports.
;
TST.B QDExist ; (Unless QuickDraw don't exist)
BNE @noQD
MOVE.L portList,D1 ; or if portlist = 0 or -1
BEQ @noQD
ADDQ.L #1,D1
BEQ @noQD
BTST #mainScreen,D0 ; is it the main scrn? (flags already in D0)
BEQ @notMain
PEA oldPort(A6) ; Save the current port
_GetPort
MOVE.L mainDevice,theGDevice ; and set to the screen
MOVE.L PortList,A4 ; A4 = handle to list of ALL ports
MOVE.L (A4),A4 ; A4->list of all ports
MOVE (A4),D3 ; D3 = number of ports that exist
BRA @portWalkEnd
@portWalkLoop
MOVE.L PortList,A4
MOVE.L (A4),A4
MOVE.L 2(A4,D3.W*4),A4 ; A4 = this port
MOVE.L A4,-(SP) ; Set to each port in the port list
_SetPort
MOVE.L oldBaseAddr(A6),D1 ; D1 = the scrnbase of ports to change
BTST #7,portVersion(A4) ; high bit set?
BEQ.S @oldPort
MOVE.L portPixMap(A4),A4 ; A4 = handle to the port's pixmap
MOVE.L (A4),A4 ; A4->port's pixmap
CMP.L baseAddr(A4),D1 ; same as the screen's?
BNE.S @portWalkEnd ; no, skip this port
MOVE.L baseAddr(A3),baseAddr(A4) ; replace a bunch of fields
MOVE rowBytes(A3),rowBytes(A4)
MOVE.L pixelType(A3),pixelType(A4) ; (gets pixelSize, too)
MOVE.L cmpCount(A3),cmpCount(A4) ; (gets cmpSize, too)
MOVE.L planeBytes(A3),planeBytes(A4)
PEA oldColor(A6) ; placeholder for reinstantiating colors
MOVE.L (SP),-(SP)
MOVE.L (SP),-(SP)
MOVE.L (SP),-(SP)
_SaveFore ; Save and restore the foreground color
_RestoreFore ; (Allowing for pmFore)
_SaveBack ; And the same for the background
_RestoreBack
BRA.S @portWalkEnd
@oldPort
CMP.L portBits+baseAddr(A4),D1 ; same base on old port?
BNE.S @portWalkEnd
MOVE.L baseAddr(A3),portBits+baseAddr(A4)
MOVE rowBytes(A3),D1
AND #nurbMask,D1 ; handle NURBs here
MOVE D1,portBits+rowBytes(A4)
@portWalkEnd
DBRA D3,@portWalkLoop
MOVE.L oldPort(A6),-(SP) ; restore the pre-existing port
_SetPort
MOVE.L oldBaseAddr(A6),D1
CMP.L scrnBase,D1 ; fix scrnBase too, if neede
BNE.S @notMain
MOVE.L baseAddr(A3),scrnBase
@notMain
_AllocCursor
_ShowCursor
@noQD
;
; notify the Palette Manager that the mode has changed
;
; <2.6> moved after GDRect has been adjusted <2.6>
CMP.L #-1,PMgrHandle ; has the Palette Mgr been initialized?
BEQ.S @noPMgr ; nope, so skip this
MOVE.L GDH(A6),-(SP) ; push the device handle
_RestoreDeviceClut ; call the Palette Manager Unhook device vector
@noPMgr
MOVE.L SaveDevice(A6),theGDevice ; restore theGDevice
MOVE.L GDPMap(A2),A0 ; get pixMap handle
MOVE GDPState(A6),D0 ; get the lock state
_HSetState ; restore prior state
MOVE.L GDH(A6),A0 ; get the gDevice handle
MOVE GDHState(A6),D0 ; get the lock state
_HSetState ; restore prior state
MOVEM.L (SP)+,D3/A2-A4 ; restore work registers
UNLINK result-return-4,'INITGDEV'
ENDPROC
ENDIF
;---------------------------------------------------
;
; procedure myInitMenus;
;
; This code patches InitMenus. It would be better to call InitPalettes from InitWindows
; but MultiFinder has that patched out and we would again have to duplicate our efforts.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (InitMenus) (myInitMenus)
myInitMenus PROC EXPORT
ROMInitMenus Equ $109EE ; AWC.PB506
JsrRom ROMInitMenus ; call InitMenus AWC.PB506
_InitPalettes ; set up the AppPalette AWC.PB520
Rts ; go home AWC.PB520
;---------------------------------------------------
;
; procedure myNewCWindow()
;
; Initialize the palette manager fields of the new window.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewCWindow) (myNewCWindow)
myNewCWindow PROC EXPORT
ROMNewCWindow EQU $0F9F6 ; normal NewCWindow routine <PB302>
; shuffle parameters so it will return to us
MOVE.L SP,A0 ; get src for params
MOVE.L SP,A1 ; get dst for params
MOVE.L (A0)+,D1 ; save RTS
MOVEQ #7,D0 ; move 8 longs
@NxtLong MOVE.L (A0)+,(A1)+ ; move a long
DBRA D0,@NxtLong ; repeat for all longs
MOVE.L D1,30(SP) ; stuff original RTS
JSRROM ROMNewCWindow ; call NewCWindow <PB302>
; always set the default palette to 0
MOVE.L (SP),A1 ; get the window
MOVE.L GrafVars(A1),A0 ; get handle to vars
MOVE.L (A0),A0 ; point to vars
CLR.L PMFgColor(A0) ; and clear palette
MOVE.L (SP)+,A1 ; get window pointer
MOVE.L (SP),A0 ; get return address
MOVE.L A1,(SP) ; stuff wPtr
JMP (A0) ; and return
;---------------------------------------------------
;
; procedure myNewWindow();
;
; When NewWindow is called, do an ActivatePalette in case there's a default palette.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewWindow) (myNewWindow)
myNewWindow PROC EXPORT
ROMNewWindow EQU $0FA08 ; normal NewWindow routine <PB302>
; shuffle parameters so it will return to us
MOVE.L SP,A0 ; get src for params
MOVE.L SP,A1 ; get dst for params
MOVE.L (A0)+,D1 ; save RTS
MOVEQ #7,D0 ; move 8 longs
@NxtLong MOVE.L (A0)+,(A1)+ ; move a long
DBRA D0,@NxtLong ; repeat for all longs
MOVE.L D1,30(SP) ; stuff original RTS
JSRROM ROMNewWindow ; call NewWindow <PB302>
MOVE.L (SP),-(SP) ; push the window
_ActivatePalette ; and activate the system palette
@DONE MOVE.L (SP)+,A1 ; get window pointer
MOVE.L (SP),A0 ; get return address
MOVE.L A1,(SP) ; stuff wPtr
JMP (A0) ; and return
;---------------------------------------------------
;
; procedure HiliteWindow();
;
; Patch HiliteWindow to call ActivatePalette if called from SelectWindow
; AND if it is not called from MoveWindow!
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (HiliteWindow) (myHiliteWindow)
myHiliteWindow PROC EXPORT
FromSelect EQU $1016A ; RTS if called from select <PB302>
FromMove EQU $10396 ; RTS if selected from Move <PB302>
ROMHilite EQU $0FFCE ; real HiliteWindow <PB302>
CMPRA FromSelect,(SP) ; from selectWindow? <PB302>
BNE.S @JustHilite ; => no, just hilite
CMPRA FromMove,$38(SP) ; from Move? <PB302>
BEQ.S @JustHilite ; => yes, just hilite
TST.B 4(SP) ; hiliting?
BEQ.S @JustHilite ; => no, just (un)hilite
LEA 6(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE -(A0),-(SP) ; push boolean
JSRROM ROMHilite ; call hilite in ROM <PB302>
MOVE.L 6(SP),-(SP) ; push window pointer
_ActivatePalette ; and activate its palette
RTD #6 ; strip 6 bytes params and return
@JustHilite JMPROM ROMHilite ; and complete the call <PB302>
;---------------------------------------------------
;
; procedure MyMoveWindow
;
; Patch MoveWindow to call ActivatePalette
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MoveWindow) (myMoveWindow)
MyMoveWindow PROC EXPORT
ROMMove EQU $0FD9C ; real MoveWindow <PB302>
LEA 10(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE.L -(A0),-(SP) ; push dst location
MOVE -(A0),-(SP) ; push frontflag
JSRROM ROMMove ; call movewindow <PB302>
MOVE.L 10(SP),-(SP) ; push window
_ActivatePalette ; and activate its palette
RTD #10 ; strip 10 bytes and return
;---------------------------------------------------
;
; procedure MySizeWindow
;
; Patch SizeWindow to call MySetPalette
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SizeWindow) (mySizeWindow)
MySizeWindow PROC EXPORT
ROMSize EQU $1000E ; real SizeWindow <PB302>
LEA 10(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE.L -(A0),-(SP) ; push dst location
MOVE -(A0),-(SP) ; push frontflag
JSRROM ROMSize ; call SizeWindow <PB302>
MOVE.L 10(SP),-(SP) ; push window
_ActivatePalette ; and activate its palette
RTD #10 ; strip 10 bytes and return
;---------------------------------------------------
;
; procedure MyClose
;
; Patch CloseWindow to call DisposPalette. In the initial system disk release, this
; patch mistakenly operated on DisposeWindow instead of CloseWindow.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CloseWindow) (myClose)
MyClose PROC EXPORT
ROMClose EQU $0FB6E ; real CloseWindow <PB302>
MOVE.L 4(SP),A0 ; get the window
TST PORTBITS+ROWBYTES(A0) ; is it new?
BPL.S @NotNew ; => no
MOVE.L GrafVars(A0),A0 ; get grafVar handle
MOVE.L (A0),A0 ; point at grafVars
MOVE.L PmFgColor(A0),D0 ; is there a palette
BEQ.S @NotNew ; => no
Move.L D0,A0 ; let's use an address register AWC.PB457
Move.L (A0),A0 ; dereference it AWC.PB457
BTst #DisposeBit,pmPrivate(A0) ; should we dispose of it? AWC.PB457
Beq.S @NotNew ; no => the user has to dispose of it AWC.PB457
MOVE.L D0,-(SP) ; else push palette
_DisposePalette ; and dump it
@NotNew JMPROM ROMClose ; and dispose the window <PB302>
;---------------------------------------------------
;
; procedure MyShowHide(WindowPtr; BOOLEAN);
;
; Patch MyShowHide to call ActivatePalette. If it is being called to show a hidden window,
; then do the ActivatePalette.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ShowHide) (myShowHide)
MyShowHide PROC EXPORT
ROMShow EQU $0F742 ; real ShowHide <PB302>
LEA 6(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE -(A0),-(SP) ; push boolean
JSRROM ROMShow ; call showhide <PB302>
MOVE.L A1,-(SP) ; save A1 for ShowHide!
MOVE.L 10(SP),-(SP) ; push window
_ActivatePalette ; and activate its palette
MOVE.L (SP)+,A1 ; restore A1 for ShawHide
RTD #6 ; strip 10 bytes and return
;---------------------------------------------------
;
; procedure MyExit;
;
; Patch MyExit to call DisposePalette for all palettes in the app heap. In addition, jam
; theGDevice and srcDevice with MainDevice. As if that weren't enough, make sure that
; cursor interrupts are enabled.
;
; This patch is not installed by A/UX or under MultiFinder.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MyExit) (myExit)
MyExit PROC EXPORT
EXPORT myExitExit ; address of JMP target to daisy chain <PB158>
ROMIAZInit EQU $4080DEF8 ; jump back into ROM
ROMAppZoneAddr EQU $4080D434 ; a useful routine
MOVEM.L A0-A6/D0-D4,-(SP) ; save all registers
_PMgrExit
MOVE.L MainDevice,A0 ; get the main device
MOVE.L A0,SrcDevice ; set the src device
MOVE.L A0,theGDevice ; and the current device
MOVE #$2000,SR ; make sure interrupts enabled
MOVEM.L (SP)+,A0-A6/D0-D4 ; restore all registers
JMP $4080000A ; jump to next code in chain <PB158>
myExitExit EQU *-4 ; address of JMP target <PB158>
ENDIF
; Okay, that's it. We're out of here!