mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-02-12 22:30:54 +00:00
The ROM now round-trips with QuickDraw mostly built from source. (~30% of the ROM is now built from source.)
6029 lines
228 KiB
Plaintext
6029 lines
228 KiB
Plaintext
;__________________________________________________________________________________________________
|
||
; 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
|
||
|
||