mac-rom/QuickDraw/PaletteMgr.a
Elliot Nunn 9c249dafab Reverse 68k Color QuickDraw
The ROM now round-trips with QuickDraw mostly built from source.
(~30% of the ROM is now built from source.)
2017-12-26 09:52:55 +08:00

6029 lines
228 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;__________________________________________________________________________________________________
; 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):
;
; <SM11> 10/28/93 SAH Rolled out change SM9 because it brought out bugs in the font
; manager. Rolled out change 14 because it caused the bug that
; caused change SM9. Both of these are correct changes, we just
; need to take them out until FlushFonts really flushes ALL the
; fonts (for all processes)...
; <SM10> 10-19-93 jmp Removed the ctSeed whacking (Kon explained the error of my
; ways). WeÕll have to come up with some other method to fix
; dimming.
; <SM9> 9/20/93 SAH Fixed a bug in ActivatePalette where it would always mark black
; or white tolerant entries as handled. It really needed to make
; sure they weren't explicit as well.
; <SM8> 9/13/93 SAM Added a "code" to PMExit to call _TrashProcess (HeapUtilities).
; <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 doesnÕt work right,
; but I donÕt 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 $0203 ; 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
FlushPalettes PROC EXPORT ; THIEVED FROM THE MEMORY MGR
;-----------------------------------------------------------------------
; Call DisposePalette for all palettes in the app heap.
;
; Registers: D0-D2/A0-A1
; Called by vIAZInit.
;----------------------------------------------------------------------
IMPORT AppZoneAddr
MOVEM.L A2-A3/D3,-(SP) ; save work registers
MOVE.L PMgrHandle,A2 ; get paletteMgr handle
CMP.L MinusOne,A2 ; is it there?
BEQ.S @DONE ; => 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
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 D1,D0 ; and get for routine
JSR AppZoneAddr ; in application area (or zero)? <SM30 BT>
BNE.S @FindNext ; => not in app heap
MOVE.L D1,-(SP) ; push palette handle
DC.W $AA93 ; _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
@DONE MOVEM.L (SP)+,A2-A3/D3 ; restore work registers
RTS
;---------------------------------------------------
;
; 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 ExpandMem,A0
TST $128(A0)
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
movem.l a0-a2/d0-d2,-(sp) ; Those pesky c routines <mc8>
sub.l a0,a0 ; Pass the current process (0)
moveq #12,d0 ; _TrashProcess
;_FigmentDispatch ; let everyone know this stuff is gone
dc.w $A0A4
movem.l (sp)+,a0-a2/d0-d2 ; Restore em
IF (forRom OR theFuture) THEN
MOVE.l WindowList,wList(A6) ; <SM2> FM save the current window list
ENDIF
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.B inFront(A6)
BEQ.S @doNothing
@front
JSR CheckAllDeviceCluts ; A pretty simple patch, really.
CLR -(SP) ; No Setentries on Scatter
JSR ScatterDevices
BSR CheckForJuggler ; Is Jugglertm active?
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
if 0 then
; <SAH 28OCT93>
; I'm taking this code out for now. It causes us to not add entries that we used to add. This code
; is not installed for IIci ROMs. It only began being installed for SuperMario. By taking it out we
; bring the palette manager back to the Quadra Rom but bring back a bug with tolerant+explicit+
; inhibited...
BMI.S ExplLoopEnd ; Already handled?
endif
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
MOVE $14(A3),D0
AND #$8010,D0
BEQ.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 MOVE $14(A3),D0
AND #$8010,D0
BEQ.S UnlockPltt
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
MOVE $14(A0),D0
AND #$8010,D0
BEQ 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