mac-rom/QuickDraw/Patches/PaletteMgrPatch.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

3731 lines
160 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

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

;EASE$$$ READ ONLY COPY of file ÒPaletteMgrPatch.aÓ
; 1.0 BAL 11/19/1989 Changed name to avoid conflicts between system 6.0 and
; ROM/32-Bit QD versions.
; -- Revisions Of PaletteMgr.a Below --
; 1.5 SES 08/28/1989 Removed references to nFiles. Updated equates accordingly.
; 1.4 BAL 06/26/1989 dvb For 6.0.4 Moved grayrgn test into initpalettes, removed initmenus
; 1.3 BAL 06/12/1989 Altered patch to InitMenus to check grayRgn before calling _InitPalettes
;¥1.2 CEL 06/10/1989 Moved Private.a QuickDraw Equates into proper QuickDraw
; private file (colorequ.a), got rid of QuickDraw nFiles dependencies
; and fixed up necessary filesÉ
;¥1.1 CCH 11/16/1988 Updated to newest version.
;
;_______________________________________________________________________________________
; File: PaletteMgr.a
;
; Version 6.0.1
;
; Copyright 1987-1988 Apple Computer, Inc. All Rights Reserved
;
;_______________________________________________________________________________________
;
; modification history
;
; <02feb87> AWC new this date
; <26mar87> PB103 AWC non-window manager version completed
; <27mar87> AWC interface changed to support window manager
; <27mar87> EHB window manager calls added
; <29mar87> PB150 AWC fixed nil pointers (RGBForeColor) and added WindowCopy
; <30mar87> AWC/EHB background updates, ExitToShell fix, System Palette
; <30Mar87> JTC Daisy chain the IAZInit routine properly.
; <15Jul87> AWC/FJL SetPalette(Ptr(-1),...), Menu fix, update problems
; <20Jul87> PB212 DAF Removed GetNewCWindow portion of NewCWindow fix. Changed
; myDisposeWindow to fix CloseWindow.
; <22Jul87> PB221 AWC fix to crash when there are no menus (see note @PB225)
; <22Jul87> PB222 AWC CopyPalette implemented (see note @PB225)
; <22Jul87> PB223 AWC fix to bug causing too many updates (see note @PB225)
; <22Jul87> PB224 AWC added support for Juggler (see note @PB225)
; <22Jul87> PB225 AWC NewPWindow implemented; NOTE: fixes PB221 through PB225
; were all added at once. They are unique numbers solely
; for bureaucratic reasons.
; <12Aug87> C864 RWH Added ROMPaletteMgr Conditional flag (its defined outside this file
; in order to make Rom78Fix build work). Conditional-ed out calls
; at end of this file so it can be put in ROM. Search for ;!!!!!
; Made ReDrawMenuBar an RTS for the ROM version. Made the call to
; SortPoints use the macro from QDHooks.a.
; <01Sep87> PB259 AWC Fixed NewPWindow so it doesn't polymerize the stack.
; C872 Same as PB259
; <04Sep87> PB262 AWC Fixed ActivatePalette to generate fewer color updates
; C886 Same as PB262
; <16Nov87> PB302 AGH Made changes for use with A/UX toolbox.
; <01Feb88> PB377 AWC Fixed 5 minor bugs in the Palette Manager (1st entry bug, screen
; dev. bug, D0 error bugs, protection bits bugs, PmBackColor/explicit
; bug)
; <02Feb88> PB378 AWC Oops, I forgot one. The 16th palette causes a crash...
; <12Feb88> PB392 AWC Fixed a fix which short circuits the menu bar update code.
; <23Mar88> PB438 DAF Removed InitWindows fix, since it wasn't installed anyway.
; <24Mar88> PB439 AWC Fixed SetPalette; removed pmWindow references
; <07Apr88> PB457 AWC Fixed ColorMore crash, implemented AppPalette, DisposeBit
; <08Apr88> PB462 AWC Fixed lines out of order bug created in PB459
; <18Apr88> PB469 AWC Blocked InitGraf from using the system resource file
; <26Apr88> PB480 AWC Fixed PaletteMgr updates, animation of black, and set Palettes NoPurge
; <29Apr88> PB485 AWC Blocked spurious ActivatePalette's by checking wHilited
; <13Jun88> PB500 AWC Fixed AnimateEntry; made Palette Manager active even if
; no 'clut' devices are present
; <17Jun88> PB506 AWC Moved InitGraf fix to InitMenus; IAZNotify routine clears WindowList
; <22Jun88> PB508 AWC Added MenuBar updates and SingleFinder Desktop updates; made routines
; draw using the AppPalette; added DirtySeeds to correct update problem;
; blocked InitMenus from initializing AppPalette twice; now clear
; AppPalette in the event that its palette is disposed
; <27Jun88> PB520 AWC Save grafPort across PaintOne; put InitMenus stuff into InitPalettes;
; removed NewPWindow (which was never publicized); generally cleaned
; things up for the ROM version. Fixed unlocked handle in PmForeColor.
; <12Jul88> PB530 AWC Fixed CopyPalette resize problem; changed behavior of explicit
; colors on direct devices
;
;___________________________________________________________________________
XPalettes PROC EXPORT ; dummy procedure; return to globals AWC.PB457
ENDPROC ; AWC.PB457
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
; Here is what is left of the Patch Collator stuff. The Palette Manager routines have never
; been patches to the ROM - they were never in the original ROM, so there was nothing to
; patch. This is all there is. The window manager patches are shown below and are marked
; near the routine with another patch signal. To find one, double click on the Patch Name
; and search for that (Command-H under MPW 2.0).
;
; File Date Patch# PMgr Routines Trap#
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (InitPalettes) $AA90
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewPalette) $AA91
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetNewPalette) $AA92
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (DisposePalette) $AA93
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ActivatePalette) $AA94
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetPalette) $AA95
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetPalette) $AA96
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (PmForeColor) $AA97
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (PmBackColor) $AA98
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (AnimateEntry) $AA99
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (AnimatePalette) $AA9A
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetEntryColor) $AA9B
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetEntryColor) $AA9C
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetEntryUsage) $AA9D
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetEntryUsage) $AA9E
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CTab2Palette) $AA9F
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (Palette2CTab) $AAA0
;AppleSystemPatch PaletteMgr.a 22Jul87 #PB222 (CopyPalette) $AAA1
;
; Fix File Date Patch# Fixed Routines Patch Routine Name
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBForeColor) (RGBForeColor)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBBackColor) (RGBBackColor)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB506 (InitMenus) (myInitMenus)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewCWindow) (myNewCWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewWindow) (myNewWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (HiliteWindow) (myHiliteWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MoveWindow) (myMoveWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SizeWindow) (mySizeWindow)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CloseWindow) (myClose)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ShowHide) (myShowHide)
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MyExit) (myExit)
;
; Another routine which must be included for proper Palette Manager operation is
; GetNewCWindow which is patched in PatchIIROM.a
;---------------------------------------------------
;
; PROCEDURE InitPalettes; INLINE $AA90;
;
InitPalettes PROC EXPORT
IMPORT RecordPalette
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
moveq #-1,d0 ; get a useful value <1.3>
cmp.l grayRgn,d0 ; has it been initialized? <1.3>
beq goHome ; no, don't call the brinker <1.3>
; 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
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
BTst #ScreenDevice,D0 ; is it a screen device?
Beq.S NextDevice ; no => examine next device AWC.PB377
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 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 #17*8,D0 ; get size
_PtrToHand ; make a handle out of it
Move.L A0,D3 ; save it
Clr.L -(SP) ; space for result
Move #16,-(SP) ; push the number of entries
Move.L A0,-(SP) ; push our handle
Move #pmTolerant,-(SP) ; all tolerant entries
Move #$4000,-(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
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.S GoHome ; no => must be good; abort AWC.PB520
Move.L D0,AppPalette ; clear the AppPalette AWC.PB508
LookForIt Tst CurApRefNum ; are we using the system resource file? AWC.PB469
Beq.S GoHome ; 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 GoHome ; 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
Lsl #1,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 pmWindow(A0) ; clear the window field just for grins 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 GoHome ; 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
GoHome MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
Unlk A6 ; clear stack frame
Rts ; go home
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
DC.W $0002,$C000,$C000,$C000 ; light gray
DC.W $0003,$8000,$8000,$8000 ; medium gray
DC.W $0004,$4000,$4000,$4000 ; dark gray
DC.W $0005,$DD6B,$08C2,$06A2 ; Apple red
DC.W $0006,$FFFF,$648A,$028C ; Apple orange
DC.W $0007,$FC00,$F37D,$052F ; Apple yellow
DC.W $0008,$1F21,$B793,$1431 ; Apple green
DC.W $0009,$0000,$0000,$D400 ; Apple blue
DC.W $000A,$46E3,$0000,$A53E ; Apple violet
DC.W $000B,$F2D7,$0856,$84EC ;
DC.W $000C,$90D7,$7160,$3A34 ;
DC.W $000D,$0241,$AB54,$EAFF ;
DC.W $000E,$0000,$64AF,$11B0 ;
DC.W $000F,$5600,$2C9D,$0524 ;
SysColorEnd
;---------------------------------------------------
;
; 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 blue(A1),blue(A0) ; copy blue
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
Lsl #1,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 ClearPalette(cPalette: PaletteHandle); LOCAL;
;
ClearPalette PROC EXPORT
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-D3/A2-A4,-(SP) ; save registers
Move.L PMgrHandle,A3 ; get palette manager handle
CmpA.L #PMgrNil,A3 ; are we initialized?
Beq 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 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
MoveQ #0,D0 ; no error
; 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
NextLink 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,DevCTab(A6) ; save color table handle, too
Move.L (A0),A0 ; dereference CTab
Cmp ctSize(A0),D2 ; is index number <= entries - 1?
Bhi.S IgnoreIt ; no => don't unreserve it
Clr ctTable+value(A0,D2.W*8) ; unreserve it
IgnoreIt Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (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
Tst D3 ; is there another link to examine?
Bmi.S NextLink ; yes => go unlink it
NextEntry Clr ciFlags(A2) ; shut down any crap
Clr.L ciPrivate(A2) ; clear it
AddA.L #ciSize,A2 ; bump A0 to the next ColorInfo
EntryEnd DBra D0,EntryLoop ; loop for all pmEntries
GoHome MoveQ #0,D0 ; clear error condition
BadPalette MoveM.L (SP)+,D2-D3/A2-A4 ; restore registers AWC.PB457
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; 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 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 register
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
;---------------------------------------------------;
; ;
; Here begins a number of routines called by ;
; ActivatePalette. These routines share its ;
; stack frame built on A6, building their own ;
; stack frames on A4. ;
; ;
;---------------------------------------------------;
;---------------------------------------------------
;
; 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;
;
AnalyzeDev PROC EXPORT
MoveM.L D3-D6/A2-A3,-(SP) ; save registers
Move DevIndexes(A6),D0 ; get number of device entries
MoveQ #0,D1 ; clear high word, put starting index in low word
Move.L InfoPtr(A6),A3 ; get pointer to scratch area
Bra.S ClearEnd ; jump into loop
ClearLoop Move.L D1,(A3)+ ; clear high word, put index in low word
AddQ #1,D1 ; bump D1 to the next index
ClearEnd DBra D0,ClearLoop ; continue for the entire Histogram
Clr Histogram(A6)
Move.L PMgrPtr(A6),A2 ; put PMgrHandle^ into A2
Move APalettes(A2),D3 ; get number of active palettes
Cmp #1,D3 ; is there just the one?
Ble.S GoHome ; yes => we're done
Add FreeSpaces(A2),D3 ; make D3 the total space count
Move.L InfoPtr(A6),A3 ; point A3 at beginning of Histogram
Move.L PListHandle(A2),A0 ; get PListHandle (locked down)
Move.L (A0),D5 ; save pointer to next PaletteHandle in D5
Move CurDevice(A6),D6 ; put current device into D4
Bra.S HistoEnd ; jump into loop
HistoLoop Move.L D5,A0 ; get next palette
AddQ.L #PLstEntrySz,D5 ; bump D5 to next palette
MoveA.L (A0),A0 ; get next palette into A0
CmpA.L #Nil,A0 ; is this a free space?
Beq.S HistoEnd ; yes => go examine another one
CmpA.L PaletteH(A6),A0 ; is it the current palette?
Beq.S HistoEnd ; yes => go examine another one
Move.L (A0),A0 ; dereference the palette
Move.L pmDevices(A0),D0 ; get devices
BTst D6,D0 ; is it using this device?
Beq.S HistoEnd ; no => go examine another palette
Move pmEntries(A0),D4 ; get number of palette entries
Lea pmInfo(A0),A2 ; put first ColorInfo into A2 where we can keep it
Bra.S PaletteEnd ; jump into loop
PaletteLoop Clr.L -(SP) ; push space for result
Pea ciRGB(A2) ; push address of current color
_Color2Index ; get best fit
Move.L (SP)+,D0 ; pull the index
AddQ #1,HistCount(A3,D0.W*4) ; add to histogram reference count for this index
Bpl.S NotNegative ; a safeguard
SubQ #1,HistCount(A3,D0.W*4) ; put it back positive
NotNegative AddA.L #ciSize,A2 ; bump A2 to the next ColorInfo
PaletteEnd DBra D4,PaletteLoop ; continue for all pmEntries
HistoEnd DBra D3,HistoLoop ; continue for all palettes
; well you may have wondered what's going on here. We now have an array of reference
; counts for all palettes that use this device. Each index was allowed a longint of
; space, though, and the index itself was placed in the low word of that longint during
; initialization. If we view this combination as a "point" we can use the Quickdraw
; procedure "SortPoints" to do all the sorting work for us. It uses a stack-based
; non-recursive QuickSort algorithm. The reference count in the high word is the main
; key. If two of them happen to match, we won't much worry about the fact that secondary
; sorting occurs on the index itself. However, the sort will move the indexes around, too,
; so we'll end up with a sorted list of indexes with low reference counts at the beginning
; of the list. We've taken pains to make sure we have no negative reference counts, though
; that probably wasn't necessary.
Move.L A3,-(SP) ; push address of "points"
Move DevIndexes(A6),-(SP) ; push number of points
; Jsr ([SortPoints]) ; call Quickdraw sort routine <C864>
_SortPoints ; call Quickdraw sort routine <C864>
GoHome MoveM.L (SP)+,D3-D6/A2-A3 ; restore registers
Rts ; go home
;---------------------------------------------------
;
; Function Pillage:Integer; LOCAL;
;
Pillage PROC EXPORT
ParamSize equ 0 ; total bytes of params
EntryResult equ ParamSize+10-2 ; best index we can find
VarSize equ 0
Link A4,#VarSize ; build stack frame
MoveM.L D3/D4,-(SP) ; save registers
Clr EntryResult(A4) ; clear the result to illegal
Move.L DevCTab(A6),A1 ; get pointer to device color table
Move.L (A1),A1 ; dereference it
AddA.L #ctTable,A1 ; bump A1 to the first ColorSpec
Move DevIndexes(A6),D3 ; get number of indexes
Bra.S PillageEnd ; jump int the loop
PillageLoop BTst #5,value(A1,D3.W*8) ; is this one available for pillaging?
Bne.S PillageIt ; yes => go pillage it
PillageEnd DBra D3,PillageLoop ; continue for DevIndexes entries
Bra GoHome ; quit in utter failure!
PillageIt BfClr value(A1,D3.W*8){0:3} ; unprotected, unreserved, pillaged
SubQ #1,Pillages(A6) ; one less worth pillaging
Move D3,EntryResult(A4) ; return the pillaged index
; Now, what fun! We get to fix up all the device links!
Move CurDevice(A6),D0 ; get current device
Lsl #8,D0 ; multiply by table size/4
Add D3,D0 ; add in entry offset
Move.L PMgrPtr(A6),A0 ; get base pointer
AddA.L #LinkTabs,A0 ; bump base pointer to start of LinkTabs
Move ForeLink(A0,D0.W*4),D3 ; get forward links
Move BackLink(A0,D0.W*4),D4 ; get forward links
Clr.L (A0,D0.W*4) ; clear the links away
Tst D3 ; examine forward link
Bmi.S MultiLinks1 ; if < 0 we have more than one assigned
Tst D4 ; examine backward link
Bmi.S MultiLinks2 ; if < 0 we have more than one assigned
; This was a quickie. D3 contains the palette number, D4 the entry number. All we
; need do is tell the palette it no longer has it.
And #$1FFF,D3 ; clear key bits
Move.L PListPtr(A6),A0 ; get the palette list
SubQ #1,Reserves(A0,D3*8) ; it has one less entry reserved
Move.L PaletteRef(A0,D3*8),A0 ; get the palette
Move.L (A0),A0 ; dereference it
And.L #$00001FFF,D4 ; clear high word and key bits
Lsl.L #4,D4 ; make it an offset to the ColorInfo
Clr.L pmInfo+ciPrivate(A0,D4.L) ; clear the link
Bra GoHome ; we did it!
; The forward link goes somewhere. See if the backward one does too. If so,
; jump to BothLinks.
MultiLinks1 Tst D4 ; examine backward link
Bmi.S BothLinks ; both of them go somewhere
; The forward link goes somewhere, but the backward one does not. We must remember
; the first forward link so we can copy it into the palette, then we advance
; forward by one, copy the palette entry into that, and continue searching until we find
; out what palette this is.
Move D3,D0 ; remember the forward link
BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next forward link
Move D4,BackLink(A1) ; copy the back link
Move ForeLink(A1),D3 ; get next link
Bpl.S GotPalette1 ; if > 0, we've found the palette
MultiFLoop BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move ForeLink(A0,D1.L*4),D3 ; get next link; is it positive?
Bmi.S MultiFLoop ; no => continue
GotPalette1 And #$1FFF,D3 ; clear key bits
Move.L PListPtr(A6),A0 ; get the palette list
SubQ #1,Reserves(A0,D3*8) ; it has one less entry reserved
Move.L PaletteRef(A0,D3*8),A0 ; get the palette
Move.L (A0),A0 ; dereference it
And.L #$00001FFF,D4 ; clear high word of entry
Lsl.L #4,D4 ; make it an offset to the ColorInfo
Move D0,pmInfo+ciPrivate(A0,D4.L) ; set a new link
Bra.S GoHome ; we did it!
; The backward link goes somewhere, but the forward one does not. We must advance
; backward by one, copy the palette id into it, and continue searching until we find out
; what palette this is.
MultiLinks2 BfExtU D4{19:5},D1 ; grab device number (0..31)
BfExtU D4{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next backward link
Move D3,ForeLink(A1) ; copy the forward link
Move BackLink(A1),D4 ; get next link
Bpl.S GotPalette2 ; if > 0, we've found the palette
MultiBLoop BfExtU D4{19:5},D1 ; grab device number (0..31)
BfExtU D4{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move BackLink(A0,D1.L*4),D4 ; get next link; is it positive?
Bmi.S MultiBLoop ; no => continue
Bra.S GotPalette2 ; share common code
; We're in the middle of the list somewhere. We'll step one backward and copy
; the forelink from the current entry, then we'll step one foreward and copy
; the backlink from the current entry. Then we'll keep going forward until we
; find the palette. All we need do is decrement its reference count, so we don't
; need the entry number.
BothLinks BfExtU D4{19:5},D1 ; grab device number (0..31)
BfExtU D4{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next backward link
Move D3,ForeLink(A1) ; copy the forward link
BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A0,D1.L*4),A1 ; point A1 at next foreward link
Move D4,BackLink(A1) ; copy the backward link
Move ForeLink(A1),D3 ; get next foreward link
Bpl.S GotPalette2 ; if > 0, we've found the palette
BothLoop BfExtU D3{19:5},D1 ; grab device number (0..31)
BfExtU D3{24:8},D2 ; grab index number (0..255)
Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Move ForeLink(A0,D1.L*4),D3 ; grab next forward link
Bmi.S BothLoop ; if < 0, we keep looking
GotPalette2 Move.L PListPtr(A6),A0 ; get the palette list
And #$1FFF,D3 ; clear away key bits
SubQ #1,Reserves(A0,D3*8) ; it has one less entry reserved
GoHome MoveM.L (SP)+,D3/D4 ; restore registers
Unlk A4 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE ReserveColor(myEntry:integer); LOCAL;
;
ReserveColor PROC EXPORT
ParamSize equ 2 ; total bytes of params
myEntry equ ParamSize+8-2 ; number of ColorInfo to reserve
VarSize equ 0
Link A4,#VarSize ; build stack frame
Move Histogram(A6),D0 ; get next entry to examine
Move DevIndexes(A6),D1 ; get number of indexes for this device
Sub D0,D1 ; calculate number of possibilites left
Ble.S NoneLeft ; none => quit, leaving color unhandled
Move.L InfoPtr(A6),A0 ; get pointer to histogram
Move.L DevCTab(A6),A1 ; get device CTabHandle
Move.L (A1),A1 ; dereference it
AddQ.L #ctTable,A1 ; bump it to the first ColorSpec
Bra.S CheckEnd ; jump into the loop
CheckLoop Move HistIndex(A0,D0.W*4),D2 ; get the next index
AddQ #1,D0 ; bump Histogram to next entry
Tst D2 ; is it "white"?
Beq.S CheckEnd ; yes => ignore it
Cmp BlackIndex(A6),D2 ; is it "black"?
Beq.S CheckEnd ; yes => ignore it
BTst #reserveBit,value(A1,D2.W*8); is this entry reserved? <1.5>
Beq.S FoundOne ; no => we've got it!
CheckEnd DBra D1,CheckLoop ; continue for all remaining indexes
; We've used all available unreserved entries. Now we look to see if we can pillage
; anything from the device table.
NoneLeft Move D0,Histogram(A6) ; mark Histogram as done
Tst Pillages(A6) ; is there anything to pillage?
Beq GoHome ; no => quit
Clr -(SP) ; function result
Jsr Pillage ; get an entry by pillaging
Move.L DevCTab(A6),A1 ; restore A1 AWC.PB480
Move.L (A1),A1 ; dereference it AWC.PB480
AddQ.L #ctTable,A1 ; bump it to the first ColorSpec AWC.PB480
Move (SP)+,D2 ; put it in D2; is it legal?
Bne.S TakeEntry ; yes => roust it out
Bra GoHome ; no => miserable failure
FoundOne Move D0,Histogram(A6) ; mark used portion of Histogram
TakeEntry Move.L PalettePtr(A6),A0 ; get palette pointer
MoveQ #0,D0 ; clear high word
Move myEntry(A4),D0 ; get entry number
Lsl.L #4,D0 ; calculate offset to ColorInfo
Lea pmInfo(A0,D0.L),A0 ; point A0 at ColorInfo
BSet #HandledBit,ciFlags(A0) ; mark this entry as handled
Move.L ciRGB+red(A0),RGB+red(A1,D2.W*8) ; update red and green
Move ciRGB+blue(A0),RGB+blue(A1,D2.W*8) ; update blue
AddQ #1,Updates(A6) ; we've changed something
BSet #reserveBit,value(A1,D2.W*8) ; reserve it <1.5>
; For old or new links, the BackLink will still point at the entry number | $6000
Move.L DevLinks(A6),A1 ; point A1 at LinkTab
Move myEntry(A4),D0 ; grab entry number
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
GoHome Unlk A4 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE Allocate; LOCAL;
;
Allocate PROC EXPORT
; 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,-(SP) ; save registers
Jsr AnalyzeDev ; analyze the entries used on the device
Move.L PalettePtr(A6),A2 ; get palette pointer
Move pmEntries(A2),D3 ; get number of entries
MoveQ #0,D4 ; D4 is the entry number
AddA.L #pmInfo,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
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)+,D0 ; pop the index result
Bne.S GotEntry ; true => it's still there - mark it as "handled"
; We will be allocating an entry for animation. If this is the first allocation, call
; AnalyzeDev to fill the scratch handle with the histogram for this device.
Move D4,-(SP) ; push entry number
Jsr ReserveColor ; try to reserve it
BTst #HandledBit,ciFlags(A2) ; did it succeed?
Bne.S NextAnimate ; yes => keep trying
Clr Tolerators(A6) ; don't bother with tolerators
Bra.S GoHome ; and go home
GotEntry 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 DBra D3,AnimateLoop ; loop for all pmEntries
GoHome MoveM.L (SP)+,D3/D4/A2 ; restore registers
Rts ; strip parameters and go home
;---------------------------------------------------
;
; FUNCTION DeltaRGB(ColorInfo,ColorSpec:Ptr):integer; LOCAL;
;
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
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
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
ENDF
;---------------------------------------------------
;
; PROCEDURE Correlate; LOCAL;
;
; This function uses the stack frame built upon A6 and builds its own stack frame on A4.
Correlate PROC EXPORT
ParamSize equ 0 ; total bytes of params
MoveM.L D3-D7/A2-A4,-(SP) ; save registers
; The InfoHandle is actually twice as large as we need, so we can just clear half of it
; without worrying about boundary conditions. We do, however, assume that DevIndexes is
; a multiple of 2.
Move.L InfoPtr(A6),A0 ; get pointer to scratch area
Move DevIndexes(A6),D0 ; maximum number of device indexes
Lsr #1,D0 ; divide by 2 because we clear longs
Bra.S ZeroEnd ; jump into the DBra
ZeroLoop Clr.L (A0)+ ; clear two palette reference fields
ZeroEnd DBra D0,ZeroLoop ; loop for half of all indexes
; The ciPrivate longint is used as a record containing two distinct fields. The first
; is in the high word and is reserved for the best index we can find. The low word is
; used to hold the DeltaRGB value for that index.
;
; A2 - points to pmInfo
; A3 - points to DevCTab^^.ctTable
; A4 - points to device scratch table
;
; D3 - keeps track of number of entries left to examine
; D4 - keeps track of offset to current ColorInfo
; D5 - holds best index and offset to colliding ColorInfo
; D6 - holds number of available device entries
; D7 - hold index of current ColorInfo
Move myEntries(A6),D3 ; get number of palette entries
Move.L PalettePtr(A6),A2 ; get pointer to palette
Lea pmInfo(A2),A2 ; bump A2 to first ColorInfo
Move.L DevCTab(A6),A0 ; get device color table handle
_HLock ; lock it down
Move.L (A0),A3 ; dereference it and copy it to A4
AddQ.L #ctTable,A3 ; bump it to the first ColorSpec
Move.L InfoPtr(A6),A4 ; get pointer to our info table, freshly zeroed
MoveQ #0,D4 ; initialize D4 to first ColorInfo in palette
MoveQ #0,D7 ; initialize D7 to 0
Clr Collisions(A6) ; clear number of collisions
Move Regulators(A6),D6 ; D6 holds number of available entries
Bra AllocEnd ; jump into loop that initializes tree (no .S)
AllocLoop Move ciFlags(A2,D4.L),D1 ; grab flags; is the HandledBit set? ( < 0 )
Bmi Chosen ; yes => we've done it already
BTst #TolerantBit,D1 ; no => are we tolerating?
Beq Chosen ; no => continue
Tst D6 ; have we run out of entry space?
Bgt.S NotYet ; no => keep going
Tst Pillages(A6) ; is there an entry to pillage?
Beq.S HandleIt ; no => we can punt
Clr -(SP) ; function result
Jsr Pillage ; we'll pillage so we'll have another color
Move (SP)+,D5 ; get the result
Bra.S Pillaged ; share common code
NotYet SubQ #1,D6 ; one more available entry consumed
Clr.L -(SP) ; push longint result
Pea ciRGB(A2,D4.L) ; push address of RGBColor field
_Color2Index ; find the best match for this color
Move.L (SP)+,D5 ; get best index
Pillaged Clr -(SP) ; push DeltaRGB result
Pea ciRGB(A2,D4.L) ; push the address of the ColorInfo.ciRGB
Pea RGB(A3,D5.W*8) ; push address of index's RGBColor
Jsr DeltaRGB ; calculate and set ciPrivate+2=color distance
Move (SP)+,D0 ; fetch distance
Tst D5 ; was the index white?
Beq.S CheckWhite ; yes => see if white is okay
Cmp BlackIndex(A6),D5 ; was the index black?
Bne.S NotBlack ; no => continue
; we have matched white or black. If we're within tolerance we'll mark this color as
; handled and continue. If not, we'll skip trying to pick the best entry stuff. We add
; 1 to D6 because we know we subtracted 1 at NotYet above and didn't mean to. We should
; never get here with a pillaged entry since black or white are never supposed to be
; reserved and therefore should never be pillaged. So, it should be safe to add one
; back to D6.
CheckWhite Cmp ciTolerance(A2,D4.L),D0 ; are we within tolerance?
Bls.S BlackWhite ; yes => mark these as handled
Clr.L ciPrivate(A2,D4.L) ; clear ColorInfo.ciPrivate field
AddQ #1,Collisions(A6) ; bump number of collisions
Bra.S Chosen ; share common code
BlackWhite AddQ #1,D6 ; don't count black or white
HandleIt BSet #HandledBit,ciFlags(A2,D4.L) ; set the handled bit
Bra.S Chosen ; share common code
NotBlack Lea (A4,D5.W*2),A1 ; point A1 at the DevTab entry for this index
MoveQ #0,D1 ; clear high word
Move (A1),D1 ; is there an entry here already (<> 0)
Beq.S PickCurrent ; no => mark the current entry as chosen
; We have a collision. The index to which we just matched is already used. Look
; to see which of the two entries has the lower DeltaRGB.
And #$7FFF,D1 ; clear away the "taken" bit AWC.PB377
AddQ #1,Collisions(A6) ; bump number of collisions
Lsl.L #4,D1 ; convert D1 to an offset to its ColorInfo
Move ciPrivate+2(A2,D1.L),D2 ; get tolerance of colliding entry
Cmp D0,D2 ; which unsigned value is lower?
Bhi.S SwapEntries ; current value => swap them PB262/C886
Clr.L ciPrivate(A2,D4.L) ; clear current index
Bra.S Chosen ; share common code
SwapEntries Clr.L ciPrivate(A2,D1.L) ; mark former entry index as unassigned
PickCurrent Move D5,ciPrivate(A2,D4.L) ; set index of current ColorInfo
Move D0,ciPrivate+2(A2,D4.L) ; set tolerance of current ColorInfo
Move D7,(A1) ; put it in the device index table
BSet #7,(A1) ; mark it as taken AWC.PB377
Chosen Add.L #ciSize,D4 ; bump D4 to offset of next ColorInfo
AddQ #1,D7 ; bump D7 to next ColorInfo
AllocEnd DBra D3,AllocLoop ; loop for all pmEntries
Tst Collisions(A6) ; have we any more work to do
Beq.S SetColors ; no => go examine tolerances
; STAGE 2 - make sure jumping to SetColors is warranted - notice we still look for
; unresolved colors the way it is currently written.
; In this section we try to find a unique index for each entry in the color table. We start
; by examining each index in the device for the reserved bit. If it is reserved we enter
; a value in our dev table so we won't try to match with it (we enter black's index). We
; run down the palette and find each entry which is a) not handled, b) tolerant, and
; c) unassigned (ciPrivate field is 0, white). Then we search the available colors one
; by one, finding the best match among the ones left by using DeltaRGB.
; A3 - points to DevCTab^^.ctTable
; A4 - points to device scratch table
; D0 - keeps track of number of ColorSpecs left to examine
; D1 - holds value of BlackIndex, used to mark indexes as reserved
Move DevIndexes(A6),D0 ; number of entries to mark
Move BlackIndex(A6),D1 ; mark entries as taken using "black"
Bra.S MarkEnd ; jump into loop
MarkLoop BTst #reserveBit,value(A3,D0.W*8); is this entry reserved? <1.5>
Beq.S MarkEnd ; no => continue
Move D1,(A4,D0.W*2) ; mark it as reserved in device info list
MarkEnd DBra D0,MarkLoop ; continue
Move D1,(A4) ; mark white as taken
Move D1,(A4,D1.W*2) ; mark black as taken
; A2 - points to current ColorInfo
; A3 - still points to DevCTab^^.ctTable
; D0 - used as a temp
; D3 - keeps track of number of entries left to examine
SetColors Move myEntries(A6),D3 ; potential number of entries to resolve
MoveQ #0,D4 ; ColorInfo entry counter
Bra ResolveEnd ; jump into loop
; By the time we reach this point a ColorInfo is either Tolerant or Handled.
ResolveLoop Tst ciFlags(A2) ; has this ColorInfo been handled?
Bmi NextCInfo ; yes => continue (.S won't fit)
Tst ciPrivate(A2) ; have we assigned an index yet?
Bne.S Resolved ; yes => continue
; Resolve this entry by searching for the best match from the available indexes
Move.L InfoPtr(A6),A1 ; get device info pointer
MoveQ #0,D0 ; clear entry counter
Move DevIndexes(A6),D1 ; get number of device entries
Move #$FFFF,ciPrivate+2(A2) ; set fit to worst
Bra.S FindEnd ; start loop
FindLoop Tst (A1,D0.W*2) ; is this index available?
Bne.S NextGuy ; no => try the next guy
MoveM.L D0-D1/A1,-(SP) ; save the current registers
Clr -(SP) ; push DeltaRGB result
Pea ciRGB(A2) ; push the address of the ColorInfo.ciRGB
Pea RGB(A3,D0.W*8) ; push address of index's RGBColor
Jsr DeltaRGB ; calculate and set ciPrivate+2=color distance
Move (SP)+,D0 ; fetch the distance
Tst ciPrivate(A2) ; have we anything yet?
Beq.S StuffIt ; no => use it
Cmp ciPrivate+2(A2),D0 ; is it closer or equal to what we last had?
Bhs.S NotBetter ; no => continue
StuffIt Move D0,ciPrivate+2(A2) ; remember better fit
MoveM.L (SP)+,D0-D1/A1 ; restore registers
Move D0,ciPrivate(A2) ; remember better index
Bra.S NextGuy ; continue
NotBetter MoveM.L (SP)+,D0-D1/A1 ; restore registers
NextGuy AddQ #1,D0
FindEnd DBra D1,FindLoop
Move ciPrivate(A2),D0 ; get best index
; if the result is 0 we've not found it, and we have a system error. While it would be
; good to find this, it's better to do something "robust" for a released version, so we'll
; jump ahead to GoodEnough and avoid any updates.
Beq.S GoodEnough ; internal palette manager error; leave quietly
; MoveQ #1,D0 ; clear the index <AWC>
FoundIt Move D0,ciPrivate(A2) ; shove the index into the field
Move #1,(A1,D0.W*2) ; mark dev info list as being taken
Clr -(SP) ; push DeltaRGB result
Pea ciRGB(A2) ; push the address of the ColorInfo.ciRGB
Move ciPrivate(A2),D0 ; fetch the entry we just assigned
Pea RGB(A3,D0.W*8) ; push address of index's RGBColor
Jsr DeltaRGB ; calculate and set ciPrivate+2=color distance
Move (SP)+,ciPrivate+2(A2) ; fetch distance
Resolved Move ciTolerance(A2),D0 ; get preferred tolerance
Cmp ciPrivate+2(A2),D0 ; is the unsigned current fit good enough?
Bhs.S GoodEnough ; yes => leave it alone
Move ciPrivate(A2),D0 ; get the index
Move.L ciRGB+red(A2),RGB+red(A3,D0.W*8) ; copy red and green to device CTab
Move ciRGB+blue(A2),RGB+blue(A3,D0.W*8) ; copy blue to device CTab
AddQ #1,Updates(A6) ; remember we've done one
GoodEnough Clr.L ciPrivate(A2) ; to keep everybody honest
NextCInfo Clr ciFlags(A2) ; we're all done with ciFlags
AddA.L #ciSize,A2 ; bump to the next ColorInfo
ResolveEnd DBra D3,ResolveLoop ; loop for all pmEntries
NoTolerant Move.L DevCTab(A6),A0 ; get handle to device color table
_HUnlock ; unlock it
MoveM.L (SP)+,D3-D7/A2-A4 ; restore registers
Rts ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE RedrawDesktop; LOCAL;
;
RedrawDesktop PROC EXPORT
Tst GrayRgnPrep(A6) ; have we set up the GrayRgn stuff? AWC.PB508
Bmi NoColorDesk ; yes => but there's nothing to do AWC.PB508
Bne.S DrawDesktop ; yes => skip the setup AWC.PB508
Move #-1,GrayRgnPrep(A6) ; initialize it to "nothing to do" AWC.PB508
Tst.B pCDeskPat ; test bit 7 of pCDeskPat AWC.PB508
Bpl.S NoColorDesk ; don't update the desktop AWC.PB508
Move.L DeskCPat,D0 ; is there a desktop pattern? AWC.PB508
Beq.S NoColorDesk ; no => don't update the desktop AWC.PB508
Move.L D0,A0 ; put the desktop pattern into A0 AWC.PB508
Move.L (A0),A0 ; dereference it AWC.PB508
Move.L PatMap(A0),A0 ; get the pixmaphandle AWC.PB508
Move.L (A0),A0 ; dereference it AWC.PB508
Move.L pmTable(A0),A0 ; get the CTabHandle AWC.PB508
Move.L (A0),A0 ; dereference it AWC.PB508
Move ctSize(A0),D1 ; get the size AWC.PB508
AddQ #1,D1 ; adjust it so the DBra works correctly AWC.PB508
AddA.L #ctTable+rgb,A0 ; bump A0 to first color spec AWC.PB508
Bra.S DeskEnd ; check for not black or white AWC.PB508
DeskLoop Move.L (A0)+,D2 ; get first AWC.PB508
Bne.S NotBlack ; not black; check white AWC.PB508
Move (A0)+,D2 ; get blue component AWC.PB508
Bne.S ColorDesk ; not black or white; do an update AWC.PB508
Bra.S DeskNext ; continue AWC.PB508
NotBlack Cmp.L #-1,D2 ; is it white? AWC.PB508
Bne.S ColorDesk ; not white; do an update AWC.PB508
Move (A0)+,D2 ; get blue component AWC.PB508
Cmp #-1,D2 ; is it white? AWC.PB508
Bne.S ColorDesk ; not white; do an update AWC.PB508
DeskNext AddQ.L #2,A0 ; bump A0 to next color AWC.PB508
DeskEnd DBra D1,DeskLoop ; continue AWC.PB508
Bra.S NoColorDesk ; nothing but black or white; skip it AWC.PB508
ColorDesk Clr.L -(SP) ; function result AWC.PB508
_NewRgn ; get a new region AWC.PB508
Move.L (SP)+,DeskRgn(A6) ; save it for later use; was it nil? AWC.PB508
Beq.S NoColorDesk ; yes => can't redraw anything AWC.PB508
Move #1,GrayRgnPrep(A6) ; signal that we have work to do AWC.PB508
DrawDesktop Move.L A3,-(SP) ; save a register AWC.PB508
Clr.L -(SP) ; function result AWC.PB508
_NewRgn ; get another new region AWC.PB508
Move.L (SP),A3 ; save it where we can keep an eye on it AWC.PB508
Move.L A3,D0 ; check for nil handle AWC.PB508
Beq.S NoRgn ; couldn't get one, so quit AWC.PB508
Move.L A2,-(SP) ; push pointer to device rect AWC.PB508
_RectRgn ; make a rectangular region out of it AWC.PB508
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB508
Move.L A3,-(SP) ; push temp region AWC.PB508
Move.L DeskRgn(A6),-(SP) ; put result back in DeskRgn AWC.PB508
_UnionRgn ; UnionRgn(DeskRgn,tempRgn,deskRgn) AWC.PB508
Move.L A3,-(SP) ; push temp region AWC.PB508
_DisposRgn ; dump it AWC.PB508
NoRgn Move.L (SP)+,A3 ; restore a register AWC.PB508
NoColorDesk Rts ; and go home AWC.PB508
;---------------------------------------------------
;
; 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.
SetDev PROC EXPORT
ResultRect equ -8 ; temp rect
OldPort equ ResultRect-4 ; 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
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
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 A0,DevEntry(A6) ; save a pointer to the current device's 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 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),ciFlags(A0) ; copy ciUsage to ciFlags
AddA.L #ciSize,A0 ; bump A0 to the next ColorInfo
InitEnd DBra D0,InitLoop ; loop for pmEntries
Move.L PalettePtr(A6),A0 ; get the palette
Move pmPrivate(A0),D3 ; get the number of this palette
And #PIdMask,D3 ; clear the flag bits
Move.L DevCTab(A6),A0 ; get device CTabHandle
Move.L (A0),A0 ; dereference it
AddA.L #ctTable,A0 ; bump A0 to the start of the table
Move.L DevLinks(A6),A1 ; get device links table
Move DevIndexes(A6),D0 ; get number of entries on this device
MoveQ #0,D4 ; clear number that belong to us
MoveQ #0,D5 ; clear number available for pillaging
Move.L PMgrPtr(A6),A2 ; get the base pointer into A2
AddA.L #LinkTabs,A2 ; bump A2 to the start of the link tabs
Bra.S CountEnd ; jump into loop
CountLoop Move ForeLink(A1,D0.W*4),D1 ; fetch the link info for this entry, theGDevice
Beq.S ClearIt ; if 0, we didn't reserve it AWC.PB377
Bpl.S EndOfLink ; if >0 then we've found the end
NextIndex BfExtU D1{24:8},D2 ; get the index number (0..255)
BfExtU D1{19:5},D1 ; grab device number (0..31)
Lsl #8,D1 ; multiply by table size/4
Add D2,D1 ; add index to table offset
Move ForeLink(A2,D1.W*4),D1 ; get the next index; is it an endlink?
Bmi.S NextIndex ; no => find the next link
EndOfLink And #PIdMask,D1 ; clear all but the important bits
Cmp D3,D1 ; is this ours?
Bne.S NotThisOne ; no => bump Pillages
AddQ #1,D4 ; bump number we still have
Move #$4000,value(A0,D0.W*8) ; devctab => no protect, reserve, nopillage, our id
Bra.S CountEnd ; share code to force the device table
NotThisOne AddQ #1,D5 ; bump number we can pillage
FixCTab Move #$6000,value(A0,D0.W*8) ; devctab => no protect, reserve, pillage, our id
Bra.S CountEnd ; continue
ClearIt Clr value(A0,D0.W*8) ; device ctab => unused
CountEnd DBra D0,CountLoop ; continue for DevIndexes device entries
Move D5,Pillages(A6) ; remember how many we can pillage
Cmp Animators(A6),D4 ; have we all we want already?
Bpl.S QuickHandle ; yes => mark them handled <AWC>
Jsr Allocate ; yes => call allocation routine
Bra.S CheckTolrnt ; do the tolerant entries <AWC>
QuickHandle Move myEntries(A6),D0 ; get the number of entries <AWC>
Move.L PalettePtr(A6),A0 ; get palette pointer <AWC>
Lea pmInfo(A0),A0 ; bump A0 to the first ColorInfo <AWC>
Bra.S QuickEnd ; jump into loop <AWC>
QuickLoop Tst ciFlags(A0) ; is it handled? <AWC>
Bmi.S NextQuick ; yes => continue <AWC>
BTst #AnimatedBit,ciFlags+1(A0) ; is it animating? <AWC>
Beq.S NextQuick ; no => leave it alone <AWC>
BSet #HandledBit,ciFlags(A0) ; mark it handled <AWC>
NextQuick AddA.L #ciSize,A0 ; bump A0 to the next ColorInfo <AWC>
QuickEnd DBra D0,QuickLoop ; continue for pmEntries <AWC>
CheckTolrnt Tst Tolerators(A6) ; are there any tolerant entries?
Beq.S CheckUpdate ; no => tidy up
Move DevIndexes(A6),D0 ; get maximum number of entries
SubQ #2,D0 ; subtract black and white
Sub Animators(A6),D0 ; subtract our animators
Sub Pillages(A6),D0 ; subtract other reserved entries
Move D0,Regulators(A6) ; this is the number of regular entries left
Jsr Correlate ; yes => resolve collisions
; Now we are ready to set some colors (for real, man!). We have been changing colors
; in the device's color table all along. Now we just need to promulgate them through
; to the device with a sequential SetEntries call, but only if Updates is greater than
; zero. In order to make the call we have to unprotect each color and set it's client
; id to "none". Then we do the SetEntries call, after which we restore the protection
; and client id (255) of all colors. Next we copy the seed from the device color table
; to the palette so we'll know we've been here. Finally we generate update events for
; all windows of palettes which have been rendered on this device, including of course
; the current palette.
CheckUpdate Tst Updates(A6) ; have we changed anything?
Beq.S NoUpdate ; no => ignore this stuff
; Perform a sequential SetEntries call using the device's own color table.
Move.L theGDevice,A0 ; get the device
Move.L (A0),A0 ; dereference it
Clr gdId(A0) ; no client id's, please
Clr -(SP) ; push starting count of 0 for SetEntries
Move BlackIndex(A6),-(SP) ; push number of entries-1
Move.L DevCTab(A6),A0 ; get color table
Move.L (A0),A0 ; dereference it
Pea ctTable(A0) ; push address of the first ColorSpec
_SetEntries ; do it
NoUpdate Move.L DevCTab(A6),A0 ; get color table
Move.L (A0),A0 ; dereference it
Move.L ctSeed(A0),D0 ; read the current device seed
Move.L PalettePtr(A6),A0 ; get the Palette pointer
Move.L pmSeeds(A0),A1 ; get the handle to the seeds
Move.L (A1),A1 ; dereference it
Move CurDevice(A6),D3 ; get device number back
Move.L D0,(A1,D3.W*4) ; update the Palette's seed
; If we did not do the SetEntries, skip this part, too.
Tst Updates(A6) ; did we do a SetEntries?
Beq GoHome ; no => jump over the update code
; Here is where we add the portion of the port that touches this device to
; the palette's window's update region.
Pea OldPort(A4) ; where to put current GrafPtr
_GetPort ; get it
Move.L theGDevice,A0 ; get theGDevice
Move.L (A0),A0 ; dereference it
Lea gdRect(A0),A2 ; get address of device rect into A2
Move gdFlags(A0),D0 ; get flags
BTst #mainScreen,D0 ; is it the main screen?
Beq.S NoMenuFix ; no => don't update the menu
Move.L MenuList,D0 ; get the MenuList handle; is it nil? AWC.PB508
Beq.S NoMenuFix ; yes => don't redraw the menu bar AWC.PB508
Move.L D0,A0 ; get ready to dereference it AWC.PB508
Tst.L (A0) ; has it been purged? AWC.PB508
Beq.S NoMenuFix ; yes => don't redraw the menu bar AWC.PB508
_DrawMenuBar ; redraw the menu bar AWC.PB508
NoMenuFix MoveQ #0,D0 ; we want no updates if no SysPalette AWC PB223
Move.L AppPalette,A0 ; fetch the application's palette, if any AWC.PB457
Move.L A0,D1 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
Bne.S UseAppPltt ; no => use the application's palette AWC.PB457
Move.L PMgrPtr(A6),A0 ; fetch our data pointer
Move.L SysPalette(A0),A0 ; fetch the system palette
Move.L A0,D1 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
Beq.S NoSysP ; yes => we update
UseAppPltt Move.L (A0),A0 ; dereference AppPalette or SysPalette AWC.PB457
Move pmPrivate(A0),D0 ; get update information AWC PB224
And #$C000,D0 ; and it with the proper flags AWC PB224
NoSysP Move D0,SysUpdates(A4) ; set update information AWC PB224
Move #JugglerTrap,D0 ; #$A88F AWC PB224
_GetTrapAddress ; find out what the trap is AWC PB224
Move.L A0,-(SP) ; save it AWC PB224
Move #UnimplementedTrap,D0 ; #$A89F AWC PB224
_GetTrapAddress ; where do unimplemented traps go AWC PB224
CmpA.L (SP)+,A0 ; are we Jugglerªing? AWC PB224
Beq.S NotJuggling ; no => handle updates the old way AWC PB224
Move.L A2,-(SP) ; push device rect on the stack AWC PB224
Move CurDevice(A6),-(SP) ; push PaletteMgr device number AWC PB224
Move SysUpdates(A4),-(SP) ; push default updates for old ports AWC PB224
Move #ColorInvalRect,-(SP) ; push the selector for _ColorInvalRect AWC PB224
_Juggler ; call Erich's disgusting C code AWC PB224
bra EndJuggling ; skip over the regular update code AWC PB224
NotJuggling Move.L WindowList,A3 ; get start of window list AWC PB224
WindowLoop Move SysUpdates(A4),D1 ; reset the default update value AWC.PB480
Move #CBackBit,D0 ; grab a constant AWC PB224
CmpA.L WindowCopy(A6),A3 ; is it us?
Bne.S NotCurrent ; no => check for background updates
Move #CForeBit,D0 ; grab a different constant AWC PB223
NotCurrent Tst.B wVisible(A3) ; is this window visible?
Beq.S NextWind ; no => do the next window <C864>
Tst PortBits+RowBytes(A3) ; is it a color window?
Bpl.S UseDefault ; no => handle an old style window AWC.PB480
Move.L GrafVars(A3),A0 ; get the extended variables handle
Move.L (A0),A0 ; dereference it
Move.L PmFgColor(A0),A0 ; get the window's palette, if any
CmpA.L #Nil,A0 ; is it nil?
Beq.S UseDefault ; yes => default to the system value AWC.PB480
Move.L (A0),A0 ; dereference the palette
Move pmPrivate(A0),D1 ; fetch the palette's update values AWC.PB480
UseDefault BTst D0,D1 ; does the caller want this update? AWC.PB480
Beq.S NextWind ; no => do the next window
; We now must check to see if the window we're examining intersects the device
; we're working upon. We'll GlobalToLocal the device rect and simultaneously
; intersect it with the window's portRect. If we detect an intersection then
; we'll have calculated the rectangle we'll need for the InvalRect. First we
; point A0 at the Bounds rect for the port so we can put DevRect in local space.
Lea PortBits(A3),A0 ; point A0 at potential bitmap AWC.PB480
Tst RowBytes(A0) ; bitmap or pixmap? AWC.PB480
Bpl.S GotBitmap ; no high bit in Rowbytes => bitmap AWC.PB480
Move.L BaseAddr(A0),A0 ; get Port's Pixmap handle AWC.PB480
Move.L (A0),A0 ; get Pixmap pointer AWC.PB480
GotBitmap Lea Bounds(A0),A0 ; advance A0 to Bounds rect AWC.PB480
Move Top(A2),D0 ; get device top AWC.PB480
Add Top(A0),D0 ; subtract bounds top AWC.PB480
Cmp PortRect+Bottom(A3),D0 ; is Dest.Top >= Port.Bottom? AWC.PB480
Bge.S NextWind ; yes => no intersection AWC.PB480
Move D0,ResultRect+Top(A4) ; save it AWC.PB480
Move Left(A2),D0 ; get device left AWC.PB480
Add Left(A0),D0 ; subtract bounds left AWC.PB480
Cmp PortRect+Right(A3),D0 ; is Dest.Left >= Port.Right? AWC.PB480
Bge.S NextWind ; yes => no intersection AWC.PB480
Move D0,ResultRect+Left(A4) ; save left AWC.PB480
Move Bottom(A2),D0 ; get bottom AWC.PB480
Add Top(A0),D0 ; subtract bounds top AWC.PB480
Cmp PortRect+Top(A3),D0 ; is Dest.Bottom <= Port.Top? AWC.PB480
Ble.S NextWind ; yes => no intersection AWC.PB480
Move D0,ResultRect+Bottom(A4) ; save bottom AWC.PB480
Move Right(A2),D0 ; get right AWC.PB480
Add Left(A0),D0 ; subtract bounds left AWC.PB480
Cmp PortRect+Left(A3),D0 ; is Dest.Right <= Port.Left? AWC.PB480
Ble.S NextWind ; yes => no intersection AWC.PB480
Move D0,ResultRect+Right(A4) ; save right AWC.PB480
Move.L A3,-(SP) ; push this window's pointer AWC.PB480
_SetPort ; make it the current port AWC.PB480
Pea ResultRect(A4) ; move device rect (local) onto the stack AWC.PB480
_InvalRect ; invalidate it AWC.PB480
NextWind Move.L NextWindow(A3),A3 ; grab the next window in the list
CmpA.L #Nil,A3 ; is it nil?
Bne WindowLoop ; no => continue
Bsr RedrawDesktop ; redraw the desktop AWC.PB508
EndJuggling Move.L OldPort(A4),-(SP) ; push old port
_SetPort ; restore old port
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
MoveM.L (SP)+,D3-D5/A2-A3 ; restore registers <AWC>
Unlk A4 ; clear stack frame
Rts ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE CalcDevs; LOCAL;
;
CalcDevs PROC EXPORT
ResultRect equ -8 ; temp rect AWC PB223
SpotLight equ ResultRect-2 ; boolean for WindowCopy = FrontWindow AWC PB223
VarSize equ SpotLight ; bytes of variables AWC PB223
Link A4,#VarSize ; build stack frame AWC PB223
MoveM.L D3-D5/A2-A3,-(SP) ; save registers AWC PB223
MoveQ #0,D3 ; clear device set AWC PB223
MoveQ #0,D4 ; clear front set AWC PB223
; Point A0 at the Bounds rect of WindowCopy
Move.L WindowCopy(A6),A3 ; get window pointer AWC PB223
Lea PortBits(A3),A0 ; point A0 at potential bitmap AWC PB223
Tst RowBytes(A0) ; is it a color window? AWC PB223
Bpl.S OldPort ; no => it's an old port AWC PB223
Move.L BaseAddr(A0),A0 ; get Port's Pixmap handle AWC PB223
Move.L (A0),A0 ; get Pixmap pointer AWC PB223
OldPort Move.L ScrnBase,D0 ; get main screen AWC PB223
Cmp.L BaseAddr(A0),D0 ; do we point at the main screen? AWC PB223
Bne GoHome ; no => it doesn't count; go home AWC PB223
Lea Bounds(A0),A0 ; advance A0 to Bounds rect AWC PB223
Lea PortRect(A3),A1 ; advance A1 to Port rect AWC PB223
; Calculate PortRect in global coordinates
Move Top(A1),D0 ; get port top AWC PB223
Sub Top(A0),D0 ; subtract bounds top AWC PB223
Move D0,WindowRect+Top(A6) ; save it AWC PB223
Move Left(A1),D0 ; get port left AWC PB223
Sub Left(A0),D0 ; subtract bounds left AWC PB223
Move D0,WindowRect+Left(A6) ; save left AWC PB223
Move Bottom(A1),D0 ; get port bottom AWC PB223
Sub Top(A0),D0 ; subtract bounds top AWC PB223
Move D0,WindowRect+Bottom(A6) ; save bottom AWC PB223
Move Right(A1),D0 ; get port right AWC PB223
Sub Left(A0),D0 ; subtract bounds left AWC PB223
Move D0,WindowRect+Right(A6) ; save right AWC PB223
; Determine whether or not this is the FrontWindow
Clr SpotLight(A4) ; SpotLight := false AWC.PB485
Clr.L -(SP) ; function result AWC.PB223
_FrontWindow ; get the current front window AWC.PB223
CmpA.L (SP)+,A3 ; is this FrontWindow? AWC.PB223
Bne.S NotSpotted ; no => continue AWC.PB485
Move.B wHilited(A3),SpotLight(A4) ; FrontWindow if highlighted AWC.PB485
NotSpotted Move.L PMgrHandle,A2 ; get PMgrHandle AWC PB223
Move.L (A2),A2 ; dereference it AWC PB223
MoveQ #0,D3 ; clear Devices in D3 AWC PB223
Move nDevs(A2),D5 ; keep device number in D5 AWC PB223
Lea DevHandles(A2),A2 ; point to the first PMgr device AWC PB223
Bra.S DeviceEnd ; jump into calc loop AWC PB223
DeviceLoop Move.L (A2,D5.W*8),A0 ; copy device handle AWC PB223
Move.L (A0),A0 ; dereference it AWC PB223
Clr -(SP) ; boolean result of SectRect AWC PB223
Pea WindowRect(A6) ; port rect in global coordinates AWC PB223
Pea gdRect(A0) ; device rect AWC PB223
Pea ResultRect(A4) ; where to shove result AWC PB223
_SectRect ; calculate intersection AWC PB223
Move (SP)+,D0 ; do they intersect? AWC PB223
Beq.S DeviceEnd ; no => don't set device bit AWC PB223
BSet D5,D3 ; set device bit in D3 AWC PB223
Move.L PDevPtr(A6),A0 ; get pointer to CLUT device list AWC PB223
Tst.B SpotLight(A4) ; is this the FrontWindow? AWC PB223
Beq.S CheckPrior ; no => see if it is FrontMost instead AWC PB223
Move.L A3,DevFrontMost(A0,D5*8); save it as the new FrontMost AWC PB223
Bra.S SetFront ; and skip ahead AWC PB223
CheckPrior CmpA.L DevFrontMost(A0,D5*8),A3; is this window frontmost on this device? AWC PB223
Bne.S DeviceEnd ; no => don't set frontmost bit AWC PB223
SetFront BSet D5,D4 ; set frontmost bit in D4 AWC PB223
DeviceEnd DBra D5,DeviceLoop ; check next device AWC PB223
GoHome Move.L D3,DeviceSet(A6) ; save device set AWC PB223
Move.L D4,FrontSet(A6) ; save frontmost set AWC PB223
MoveM.L (SP)+,D3-D5/A2-A3 ; restore registers AWC PB223
Unlk A4 ; clear stack frame AWC PB223
Rts ; strip parameters and go home AWC PB223
;---------------------------------------------------
;
; PROCEDURE ActivatePalette(dstWindow: WindowPtr); INLINE $AA94;
;
ActivatePalette PROC EXPORT
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.
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
FoundPltt Move.L A3,PaletteH(A6) ; save the palette for later
; past this point we will have locked PMgrHandle and PaletteH. We also save theGDevice
; and clear the InfoHandle variable.
Move.L A2,A0 ; copy PMgrHandle
_HLock ; lock it down
Move.L A3,A0 ; copy PaletteH
_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
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
Bra.S ExamEnd ; jump into DBra loop
ExamLoop Move ciUsage(A4),D1 ; copy ciUsage field of current entry
Cmp #pmDithered,D1 ; is it pmDithered or pmCourteous?
Ble.S HandleColor ; pmCourteous => mark as handled
BTst #ExplicitBit,D1 ; pmExplicit?
Bne.S HandleColor ; yes => mark it as handled, too
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
; Any color which can match black or white within tolerance is removed from consideration.
; We guarantee that black and white will be around, so as long as you don't have to change
; their values you can match them normally. When we correlate colors we won't allow you
; to match black or white because we'll know you would have to change them.
CheckTolrnt 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.
; Clr.L DeviceSet(A6) ; zero bitmap of devices
MoveQ #0,D4 ; clear device counter
Clr GrayRgnPrep(A6) ; GrayRgnPrep := false AWC.PB508
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
Move GrayRgnPrep(A6),D0 ; see how we faired on the desktop AWC.PB508
Beq.S NoFunStuff ; no => nothing to do AWC.PB508
Cmp #-1,D0 ; did we detect no work to do? AWC.PB508
Beq.S NoFunStuff ; yes => nothing to do AWC.PB508
SubQ.L #4,SP ; open room for the old port AWC.PB520
Pea (SP) ; push a pointer to that location AWC.PB520
_GetPort ; save the old port AWC.PB520
Move.L WMgrCPort,-(SP) ; gpush WMgrPort for SetPort AWC.PB520
_SetPort ; do it AWC.PB520
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB520
_SetClip ; clip to DeskRgn AWC.PB520
Clr.L -(SP) ; push nil AWC.PB520
_ClipAbove ; set GrayRgn AWC.PB520
Move.L DeskHook,D0 ; is there a DeskHook? AWC.PB520
Bne.S CallHook ; yes => call the deskhook AWC.PB508
Clr.L -(SP) ; push nil AWC.PB508
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB508
_PaintOne ; update the desktop AWC.PB508
Bra.S RestorePort ; catch up with the latest news AWC.PB520
CallHook Move.L D0,A0 ; put DeskHook address into A0 AWC.PB508
MoveQ #0,D0 ; pass a paint message in D0 AWC.PB508
Jsr (A0) ; let the Hook do the painting AWC.PB508
RestorePort _SetPort ; pop the old port AWC.PB520
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB508
_DisposRgn ; get rid of it 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 PalettePtr(A6),A0 ; get palette pointer
Move.L pmDevices(A0),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
; STAGE 1 - implement
;
; Loop, clearing each device we once did but no longer touch. This is a good thing to
; add in the future. For now, it won't have a lot of impact. The entries it still has
; reserved can always be pillaged by somebody else if they need them. But, in the next
; version we shall release entries as we move off a device.
Nop
NoneRsrvd 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 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;
;
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 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
Bne.S AppNotNil ; no => activate the layer palette AWC.PB457
Move.L (A1),A0 ; dereference PMgrHandle AWC.PB457
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.S 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),D1 ; 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,D1 ; 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 D1 ; is this nil?
Beq.S DontClear ; don't clear it
Move.L D1,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 D1,-(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 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
;---------------------------------------------------
;
; PROCEDURE PmForeColor(dstEntry: INTEGER); INLINE $AA97;
;
PmForeColor PROC EXPORT
EXPORT PmBackColor
; In most cases we can rely upon RGBForeColor to do all the work for us. If a simple color,
; it's the perfect thing to call. If a true color, SetPalette did the important work for us
; and it's still correct. If it's an animating entry, we might not be on a device which can
; animate this color, so we want the foreground color preestablished so we can just quit if
; our attempt to use an animating entry fails.
;
; STAGE 2 - dithering patterns are not yet provided
ParamSize equ 2 ; total bytes of params
dstEntry equ ParamSize+8-2 ; which entry to use Palette handle
CallType equ -2 ; foreground = 1, background = 0
PWindow equ CallType-4 ; window pointer
GrafVarsPtr equ PWindow-4 ; GrafVars^
SrcPalette equ GrafVarsPtr-4 ; whichever palette we decide to use AWC.PB520
VarSize equ SrcPalette ; size of local variables AWC.PB520
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,#VarSize ; build stack frame
MoveM.L A2-A3,-(SP) ; save registers
Move D0,CallType(A6) ; save the type of call
Move.L PMgrHandle,A1 ; get the main handle
CmpA.L #PMgrNil,A1 ; 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 A0,PWindow(A6) ; save it because we use it several times
Move.L GrafVars(A0),A0 ; get the data handle
Move.L (A0),A0 ; dereference it
Move.L A0,GrafVarsPtr(A6) ; save GrafVars pointer for later AWC.PB508
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 dstEntry(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
Pea ciRGB(A3) ; push address of ciRGB field
Tst CallType(A6) ; was it a background call
Bne.S DoForegrnd ; no => do the foreground call
_RGBBackColor ; yes => do the background call
Bra.S DoContinue ; keep going
DoForegrnd _RGBForeColor ; let this do almost all the work
DoContinue Move ciUsage(A3),D1 ; get flags
MoveQ #0,D0 ; clear high word
Move dstEntry(A6),D0 ; set D0 in case it is an explicit index
BTst #ExplicitBit,D1 ; is it explicit?
Bne.S DoExplicit ; yes => blast index into port
MoveQ #0,D0 ; set no error in case we go home
BTst #AnimatedBit,D1 ; no => test animation bit
Beq.S UnlockPltt ; yes => we're done AWC.PB520
Jsr FindIndex ; uses our registers - put reserved index in D0
Tst D0 ; was the result "white"?
Beq.S FixPort ; yes => give up, but set up the port first
Bra.S ShoveIndex ; share common code
DoExplicit Move.L theGDevice,A0 ; get theGDevice
Move.L (A0),A0 ; dereference it
Cmp #directType,gdType(A0) ; is it a direct device? AWC.PB530
Beq.S UnlockPltt ; yes => we're done AWC.PB530
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 PWindow(A6),A0 ; get the window pointer again
Tst CallType(A6) ; foreground? AWC.PB377
Beq.S SetBackgrnd ; no => set background AWC.PB377
Move.L D0,FgColor(A0) ; jam the index
Bra.S FixPort ; continue AWC.PB377
SetBackgrnd Move.L D0,BkColor(A0) ; jam the index AWC.PB377
FixPort Move.L GrafVarsPtr(A6),A0 ; get the GrafVars pointer again
Tst CallType(A6) ; was it background?
Beq.S DoBackgrnd ; yes => set background information
Move dstEntry(A6),PmFgIndex(A0) ; save the entry number
BSet #PmFgBit,PmFlags+1(A0) ; tell the world that we set the FgColor
Bra.S UnlockPltt ; clean up and go home AWC.PB520
DoBackgrnd Move dstEntry(A6),PmBkIndex(A0) ; save the entry number
BSet #PmBkBit,PmFlags+1(A0) ; tell the world that we set the BkColor
UnlockPltt Move.L SrcPalette(A6),A0 ; get whichever palette we used AWC.PB520
_HUnlock ; unlock it AWC.PB520
GoHome MoveQ #0,D0 ; no error
MoveM.L (SP)+,A2-A3 ; restore register
Unlk A6 ; clear stack frame
Rtd #ParamSize ; 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
SaveGDev equ -4 ; room for saving theGDevice
Mc equ SaveGDev-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?
Bne GoHome ; yes => by definition not animating
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,ciRGB+red(A2) ; copy it to the palette AWC.PB500
Move.L D0,mc+red(A6) ; save red and green on the stack AWC.PB500
Move blue(A0),D0 ; copy blue AWC.PB500
Move D0,ciRGB+blue(A2) ; copy it to the palette AWC.PB500
Move D0,mc+blue(A6) ; save blue on the stack AWC.PB500
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,SaveGDev(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
Clr -(SP) ; push starting count of 0 for SetEntries
Move D0,-(SP) ; push number of entries-1
Pea ctTable(A0) ; 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 SaveGDev(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
SaveGDev equ -4 ; room for saving theGDevice
SaveSeed equ SaveGDev-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 #ExplicitBit,ciUsage+1(A2) ; is it explicit?
Bne.S NextEntry ; yes => by definition not animating AWC.PB500
BTst #AnimatedBit,ciUsage+1(A2) ; is it animating?
Beq.S NextEntry ; no => continue
Move.L RGB+red(A3),ciRGB+red(A2) ; copy red and green into palette
Move RGB+blue(A3),ciRGB+blue(A2) ; copy blue into palette
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.L ciRGB+red(A2),ctTable+RGB+red(A0,D4.W*8)
Move ciRGB+blue(A2),ctTable+RGB+blue(A0,D4.W*8)
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,SaveGDev(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 SaveGDev(A6),theGDevice ; restore the old GDevice
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
MoveM.L (SP)+,D3-D6/A2-A4 ; restore 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 SetEntryColor(dstPalette: PaletteHandle; dstEntry: INTEGER; srcRGB: RGBColor);
; INLINE $AA9C;
;
SetEntryColor PROC EXPORT
ParamSize equ 10 ; total bytes of params
dstPalette equ ParamSize+8-4 ; source Palette handle
dstEntry equ dstPalette-2 ; entry to set
srcRGB equ dstEntry-4 ; new color
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L dstPalette(A6),A0 ; get palette
CmpA.L #Nil,A0 ; is it nil?
Beq.S GoHome ; yes => punt AWC.PB377
Move.L (A0),A0 ; dereference it
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move dstEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs.S GoHome ; no => we're done AWC.PB377
Lsl.L #4,D1 ; multiply by number of records
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
Move.L srcRGB(A6),A1 ; get the source
Move.L red(A1),ciRGB+red(A0) ; copy red and green
Move blue(A1),ciRGB+blue(A0) ; copy blue
Move.L dstPalette(A6),-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE GetEntryUsage(srcPalette: PaletteHandle; srcEntry: INTEGER; VAR dstUsage,
; dstTolerance: INTEGER); INLINE $AA9D;
;
GetEntryUsage PROC EXPORT
ParamSize equ 14 ; total bytes of params
srcPalette equ ParamSize+8-4 ; source Palette handle
srcEntry equ srcPalette-2 ; entry number
dstUsage equ srcEntry-4 ; where to put usage
dstTolerance equ dstUsage-4 ; where to put tolerance
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L srcPalette(A6),A0 ; get palette
CmpA.L #Nil,A0 ; is it nil?
Beq.S GoHome ; yes => punt AWC.PB377
Move.L (A0),A0 ; dereference it
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move srcEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs.S GoHome ; no => we're done AWC.PB377
Lsl.L #4,D1 ; multiply by number of records
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
Move.L dstUsage(A6),A1 ; get the destination
Move ciUsage(A0),(A1) ; copy usage
Move.L dstTolerance(A6),A1 ; get the second destination
Move ciTolerance(A0),(A1) ; copy tolerance
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE SetEntryUsage(dstPalette: PaletteHandle; dstEntry,srcUsage,srcTolerance: INTEGER);
; INLINE $AA9E;
;
SetEntryUsage PROC EXPORT
ParamSize equ 10 ; total bytes of params
dstPalette equ ParamSize+8-4 ; source Palette handle
dstEntry equ dstPalette-2 ; entry number
srcUsage equ dstEntry-2 ; new usage
srcTolerance equ srcUsage-2 ; new tolerance
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L dstPalette(A6),A0 ; get palette
CmpA.L #Nil,A0 ; is it nil?
Beq.S GoHome ; yes => punt AWC.PB377
Move.L (A0),A0 ; dereference it
Move pmEntries(A0),D0 ; get the number of entries
MoveQ #0,D1 ; clear high word
Move dstEntry(A6),D1 ; get the index
Cmp D0,D1 ; is the index in range?
Bhs.S GoHome ; no => we're done AWC.PB377
Lsl.L #4,D1 ; multiply by number of records
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
Move srcUsage(A6),ciUsage(A0) ; copy usage
Move srcTolerance(A6),ciTolerance(A0) ; copy tolerance
Move.L dstPalette(A6),-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE CTab2Palette(srcCTab: CTabHandle; dstPalette: PaletteHandle; myUsage,
; myTolerance: INTEGER); INLINE $AA9F;
;
CTab2Palette PROC EXPORT
ParamSize equ 12 ; total bytes of params
srcCTab equ ParamSize+8-4 ; source ColorTable handle
dstPalette equ srcCTab-4 ; destination Palette handle
srcUsage equ dstPalette-2 ; default usage value
srcTolerance equ srcUsage-2 ; default usage tolerance
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D3/A2-A3,-(SP) ; save registers
Move.L dstPalette(A6),A2 ; get palette
CmpA.L #Nil,A2 ; is it nil?
Beq.S GoHome ; can't deal with nil here either AWC.PB377
Move.L dstPalette(A6),-(SP) ; push Palette
Jsr ClearPalette ; clear animating entries and seed handle
Bne.S GoHome ; if not zero it was a bad palette AWC.PB457
Move.L srcCTab(A6),A3 ; get color table
CmpA #Nil,A3 ; is it nil?
Beq.S GoHome ; can't deal with a nil handle AWC.PB377
Move.L (A3),A1 ; dereference it
MoveQ #0,D3 ; clear high word of D3
Move ctSize(A1),D3 ; get size-1 of CTab
AddQ #1,D3 ; D3 is number of entries in palette
Move.L A2,A0 ; copy myPalette handle
Move.L D3,D0 ; copy size
AddQ #1,D0 ; include palette header
Asl #4,D0 ; multiply by 16 bytes per entry | header
_SetHandleSize ; do it
Bne.S GoHome ; and quit if we couldn't do it AWC.PB377
Move.L A2,-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
Move.L (A2),A0 ; dereference our handle
Move D3,pmEntries(A0) ; copy size
AddA.L #pmInfo,A0 ; bump us to the first ColorInfo
Move.L (A3),A1 ; dereference source handle again
AddQ.L #ctTable,A1 ; bump A1 to the first ColorSpec
Move srcUsage(A6),D1 ; grab myUsage from parameters
Swap D1 ; put it in high word
Move srcTolerance(A6),D1 ; grab myTolerance into low word
Bra.S CopyEnd ; jump into DBra loop
CopyLoop Move.L RGB+red(A1),ciRGB+red(A0) ; copy red and green
Move RGB+blue(A1),ciRGB+blue(A0) ; copy blue
Move.L D1,ciUsage(A0) ; copy myUsage and myTolerance
Clr ciFlags(A0) ; clear private flags
Clr.L ciPrivate(A0) ; clear private links
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
CopyEnd DBra D3,CopyLoop ; decrement and branch until copy is done
GoHome MoveQ #0,D0 ; clear error AWC.PB377
MoveM.L (SP)+,D3/A2-A3 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE Palette2CTab(srcPalette: PaletteHandle; dstCTab: CTabHandle); INLINE $AAA0;
;
Palette2CTab PROC EXPORT
ParamSize equ 8 ; total bytes of params
srcPalette equ ParamSize+8-4 ; source Palette handle
dstCTab equ srcPalette-4 ; destination CTabHandle
VarSize equ 0
Link A6,#VarSize ; build stack frame
MoveM.L D3/A2-A3,-(SP) ; save registers
; first grab MyPalette and myCTab and compare them to nil
Move.L srcPalette(A6),A2 ; get source into A2
CmpA #Nil,A2 ; is it nil?
Beq.S GoHome ; punt if no palette AWC.PB377
Move.L dstCTab(A6),A3 ; get destination into A3
CmpA #Nil,A3 ; is it nil?
Beq.S GoHome ; punt if no ctab AWC.PB377
; leave size in D0; dereference both handles and capture pmEntries
Move.L (A2),A0 ; dereference myPalette
MoveQ #0,D3 ; clear high word
Move pmEntries(A0),D3 ; get number of palette entries
Move.L D3,D0 ; copy length
AddQ.L #1,D0 ; add 1 for the header
Lsl.L #3,D0 ; multiply by size of ColorSpec
Move.L A3,A0 ; put handle in A0
_SetHandleSize ; resize it
Bne.S GoHome ; <> 0 => couldn't handle it AWC.PB377
Move.L (A2),A0 ; redereference myPalette
Move.L (A3),A1 ; dereference CTab
Move D3,D0 ; copy size to a temp
SubQ #1,D0 ; ctSize is really last entry
; CHECK - what should we do with the seed? Get name of call from Ernie, again.
Clr.L ctSeed(A1) ; clear seed
Move D0,ctSize(A1) ; set size
Clr transIndex(A1) ; this is not a device ColorTable (clear hi bit)
AddQ #ctTable,A1 ; bump color table to start
AddA #pmInfo,A0 ; bump palette to start
MoveQ #0,D1 ; clear index for pixel value
Bra.S CopyEnd ; jump to start of copy
CopyLoop Move D1,value(A1) ; set pixel value
Move.L ciRGB(A0),RGB(A1) ; copy red and green
Move ciRGB+blue(A0),RGB+blue(A1) ; copy blue
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
AddQ #1,D1 ; bump pixel value
CopyEnd DBra D3,CopyLoop ; loop for all entries
GoHome MoveQ #0,D0 ; clear error condition
MoveM.L (SP)+,D3/A2-A3 ; restore registers <AWC>
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
;---------------------------------------------------
;
; PROCEDURE ClearOne(eInfo:CiInfo; BasePtr:Ptr); LOCAL;
;
ClearOne PROC EXPORT
ParamSize equ 4 ; total bytes of params
eInfo equ ParamSize+8-4 ; entry to clear
BasePtr equ eInfo-4 ; pointer to PMgrHandle^^
VarSize equ 0
Link A6,#VarSize ; build stack frame
Move.L A2,-(SP) ; save a register
Move.L eInfo(A6),A0 ; get the ColorInfo address
Move.L CiPrivate(A0),D0 ; get the current link information
Clr ciFlags(A0) ; shut down any crap
Clr.L ciPrivate(A0) ; clear it
Move.L BasePtr(A6),A1 ; set up DevListPtr
Lea DevHandles(A1),A2 ; A2 points at DevHandles
AddA.L #LinkTabs,A1 ; A1 points at LinkTabs
NextLink BfExtU D0{19:5},D1 ; grab device number (0..31)
BfExtU D0{24:8},D2 ; grab index number (0..255)
Move.L (A2,D1.W*8),A0 ; get the device handle
Move.L (A0),A0 ; dereference it
Move.L gdPMap(A0),A0 ; get handle to pixmap
Move.L (A0),A0 ; dereference pixmap
Move.L pmTable(A0),A0 ; get handle to CTab
Move.L (A0),A0 ; dereference CTab
Cmp ctSize(A0),D2 ; is index number <= entries - 1?
Bhi.S IgnoreIt ; no => don't unreserve it
Clr ctTable+value(A0,D2.W*8) ; unreserve it
IgnoreIt Lsl #8,D1 ; calculate offset to link table/4
Add D2,D1 ; offset to entry/4
Lea (A1,D1.L*4),A0 ; point A0 at next forward link
Move ForeLink(A0),D0 ; get next link
Clr.L ForeLink(A0) ; clear it for the next guy
Tst D0 ; is there another link to examine?
Bmi.S NextLink ; yes => go unlink it
Move.L (SP)+,A2 ; restore A2
Unlk A6 ; clean up our mess
Rtd #ParamSize ; go home
;---------------------------------------------------
;
; PROCEDURE CopyPalette(srcPalette,dstPalette: PaletteHandle; srcEntry,dstEntry,dstLength:
; INTEGER); INLINE $AAA1;
;
CopyPalette PROC EXPORT
ParamSize equ 14 ; total bytes of params
srcPalette equ ParamSize+8-4 ; source Palette handle
dstPalette equ srcPalette-4 ; destination palette handle
srcEntry equ dstPalette-2 ; source starting entry
dstEntry equ srcEntry-2 ; destination starting entry
dstLength equ dstEntry-2 ; length of the copy
TrimLen equ -2
VarSize equ TrimLen
Link A6,#VarSize ; build stack frame
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
Move.L PMgrHandle,A4 ; get the main handle
CmpA.L #PMgrNil,A4 ; are we initialized?
Beq GoHome ; no => punt AWC.PB377
Move.L dstPalette(A6),A2 ; get destination palette
CmpA.L #Nil,A2 ; is it nil?
Beq GoHome ; can't deal with nil here either AWC.PB377
Move.L srcPalette(A6),A3 ; get source palette
CmpA.L #Nil,A3 ; is it nil?
Beq GoHome ; can't deal with a nil handle AWC.PB377
CmpA.L A2,A3 ; does source = destination?
Beq GoHome ; we can't handle this yet AWC.PB377
MoveQ #0,D0 ; clear D0
Move dstLength(A6),D0 ; get the length of the copy
Ble GoHome ; we can quit if it's too small
Move.L D0,D3 ; copy the length
Add SrcEntry(A6),D0 ; D0 is the required length of the source
Move.L (A3),A1 ; dereference source palette
Move pmEntries(A1),D1 ; get size of source palette
Sub D0,D1 ; D1, if negative, is how much we must trim D3
Bpl.S DontTrimSrc ; no => don't trim it
Add D1,D3 ; trim back the length of the copy AWC.PB530
DontTrimSrc Move.L (A2),A0 ; dereference the destination
Move pmEntries(A0),D4 ; get the length
Move DstEntry(A6),D0 ; calculate the potential new pmEntries
Add D3,D0 ; by adding the trimmed length
Cmp D4,D0 ; need we add handle room?
Ble.S BigEnough ; no => skip _SetHandleSize AWC.PB530
Move D0,D4 ; save new length
Move.L A2,A0 ; copy DstPalette
AddQ #1,D0 ; include palette header
Asl #4,D0 ; multiply by 16 bytes per entry | header
_SetHandleSize ; do it
Bne GoHome ; and quit if we couldn't do it AWC.PB377
Move.L (A2),A0 ; dereference the destination handle
Move D4,D2 ; make a copy of the new length
MoveQ #0,D1 ; clear the high word
Move PmEntries(A0),D1 ; this is where to start clearing
Sub D1,D2 ; this is now many to clear
Move D4,pmEntries(A0) ; save size
Lea PmInfo(A0),A1 ; point us at the start of the table
Asl #4,D1 ; this is the offset to the start of the clear
AddA.L D1,A1 ; bump A1 to the start of the clear
Bra.S ClearEnd ; jump to the DBra
; The main reason for clearing is so we can correctly detect and clear entries that are
; going to be clobbered.
ClearLoop Clr.L (A1)+ ; clear 16 bytes
Clr.L (A1)+
Clr.L (A1)+
Clr.L (A1)+
ClearEnd DBra D2,ClearLoop
BigEnough CmpA.L A2,A3 ; does SrcPalette = DstPalette?
Beq.S GoHome ; yes => can't handle this AWC.PB377
Move.L A3,-(SP) ; push the palette handle AWC.PB508
Bsr DirtySeeds ; clear the device seeds AWC.PB508
Move.L (A3),A1 ; dereference source palette
MoveQ #0,D0 ; clear the high word
Move DstEntry(A6),D0 ; get the first destination
Asl.L #4,D0 ; multiply by 16
Move.L (A2),A0 ; dereference destination palette again AWC.PB508
Lea PmInfo(A0,D0),A0 ; point A0 at the first destination
MoveQ #0,D1 ; clear the high word
Move SrcEntry(A6),D0 ; get the first source
Asl.L #4,D0 ; point A0 at the first destination
Lea PmInfo(A1,D0),A1 ; point A1 at the first source
Bra.S CopyEnd ; jump into the loop
CopyLoop Move.L ciPrivate(A0),D0 ; get the link info
Beq.S NoLinks ; no => it doesn't need clearing
MoveM.L A0-A1,-(SP) ; save registers
Move.L A0,-(SP) ; ciInfo to clear
Move.L (A4),-(SP) ; dereference PMgrHandle and push it
Jsr ClearOne ; clear the links
MoveM.L (SP)+,A0-A1 ; restore interesting registers
NoLinks Move.L ciRGB(A1),ciRGB(A0) ; copy first two words
Move.L ciRGB+Blue(A1),ciRGB+blue(A0) ; copy blue and usage
Move ciTolerance(A1),ciTolerance(A0) ; copy tolerance
Clr ciFlags(A0) ; clear the flags field
Clr.L ciPrivate(A0) ; clear the links field
AddA.L #CiSize,A0 ; bump both pointers
AddA.L #CiSize,A1
CopyEnd DBra D3,CopyLoop ; loop for (trimmed) length entries
GoHome MoveQ #0,D0 ; clear error code AWC.PB377
MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
Unlk A6 ; clear stack frame
Rtd #ParamSize ; strip parameters and go home
; Thus ends the PaletteManager - ah, a sad thing it is, to be done. But WAIT! There's
; MORE! Let's patch RGBFORECOLOR and RGBBACKCOLOR just for grins! Yeah!
IF not ROMPaletteMgr THEN ; no patches for the ROM version RWH.C864
;---------------------------------------------------
;
; procedure RGBForeColor (Color : RGBColor);
;
; This routine takes an RGB triple and sets the current Graf- or CGrafPort
; fields so that drawing will take place with the best match of the
; requested color, using the current GDevice's color matching rules. The
; appropriate fields are set depending on portType
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBForeColor) (RGBForeColor)
RGBForeColor PROC EXPORT
EXPORT RGBBackColor,RGB2OLD
StdDevCall Equ $1D2A0 ; RGBForeColor; RGBBackColor is $4081D2B0 <PB302>
StdDevMask Equ $FFFFFFEF ; the calls are different only at bit 4!
MOVEQ #FGCOLOR,D0 ; get offset to index field
MOVEQ #RGBFgColor,D1 ; get offset to RGB field
SHARE MOVE.L 4(SP),A1 ; point at the RGB color
MOVE.L GRAFGLOBALS(A5),A0 ; get the QuickDraw globals pointer
MOVE.L THEPORT(A0),A0 ; point at the port
PEA 0(A0,D0) ; save pointer to the index field
TST PORTBITS+ROWBYTES(A0) ; is it a new port?
BMI.S NEWPORT ; => yes, set RGB components
JSR RGB2OLD ; else convert RGB to old color
BRA DONE ; =>
; To keep the stack correct we will momentarily preempt A1. We can restore it in a bit.
; Also, since we no longer need the offset to the index field
NewPort Move.L GrafVars(A0),A1 ; get the GrafVars handle
CmpA.L #Nil,A1 ; is it nil?
Beq.S PuntPmCalls ; yes => punt and do the normal call
Move.L (A1),A1 ; dereference it into A1
Move.L 4(SP),D2 ; get the return address
Sub.l ROMBase, D2 ; Make it offset within ROM, <PB302>
And.L #StdDevMask,D2 ; and it with the std mask
Cmp.L #StdDevCall,D2 ; is it from StdDevLoop?
Bne.S NormalCall ; no => make the normal call
Tst.L PmFgColor(A1) ; is there a palette? EHB.PBnnn
Bne.S FoundAPltt ; yes => we can do it AWC.PB508
Tst.L AppPalette ; is there an AppPalette? AWC.PB508
Beq.S NormalCall ; => no, do normal call EHB.PBnnn
FoundAPltt Move PmFlags(A1),D2 ; get the Palette Manager flags AWC.PB508
Cmp #FgColor,D0 ; was it forecolor?
Bne.S GetBack ; no => get back color flag
BTst #PmFgBit,D2 ; did PmForeColor set up this port?
Beq.S PuntPmCalls ; no => continue normally
AddQ #4,SP ; we won't need the pointer to the index
Move pmFgIndex(A1),-(SP) ; push the entry number
_PmForeColor ; set the port using PmForeColor
Bra.S GoHome ; all finished
GetBack BTst #PmBkBit,D2 ; did PmBackColor set up this port?
Beq.S PuntPmCalls ; no => continue normally
AddQ #4,SP ; we won't need the pointer to the index
Move pmBkIndex(A1),-(SP) ; push the entry number
_PmBackColor ; set the port using PmBackColor
Bra.S GoHome ; all through
NormalCall Move PmFlags(A1),D2 ; get flags
Cmp #FgColor,D0 ; is this a foreground call?
Bne.S NotFgCall ; no => clear PmBkBit
BClr #PmFgBit,D2 ; clear the foreground flag bit
Bra.S CommonFlags ; reunite it
NotFgCall BClr #PmBkBit,D2 ; clear the background flag bit
CommonFlags Move D2,PmFlags(A1) ; save the flags to GrafVars
PuntPmCalls Move.L 8(SP),A1 ; restore the pointer to the RGBColor
; Here is the normal RGBForeColor code code
MOVE.L red(A1),red(A0,D1) ; copy red and green components to the port
MOVE.W blue(A1),blue(A0,D1) ; and blue too
; make an rgbColor on the stack
MOVE.L green(A1),-(SP) ; copy green and blue
MOVE.W red(A1),-(SP) ; copy red
SUBQ #4,SP ; make room for function return
PEA 4(SP) ; push pointer to rgb
_Color2Index ; convert it to an index
MOVE.L (SP)+,D0 ; get the index result
ADDQ #6,SP ; get rid of the rgbColor
Done MOVE.L (SP)+,A0 ; get pointer to index field
MOVE.L D0,(A0) ; and set the index field
GoHome Rtd #4 ; all done
RGB2OLD
;-----------------------------------------------
;
; UTILITY TO CONVERT AN RGB (POINTED TO BY A1) VALUE
; TO AN OLD STYLE COLOR VALUE. RETURNS VALUE IN D0. CLOBBERS A0,D1
;
; USES HIGH BIT OF EACH COMPONENT TO SELECT RGB OFF (0) OR ON (1)
MOVEQ #0,D1 ; clear out D1
MOVE (A1)+,D1 ; get red
LSL.L #1,D1 ; get high bit
MOVE (A1)+,D1 ; get green
LSL.L #1,D1 ; get high bit
MOVE (A1)+,D1 ; get blue
LSL.L #1,D1 ; get high bit
SWAP D1 ; get RGB index
noBlue LEA MapTbl,A0 ; get translate table
MOVEQ #0,D0 ; clear out high word
MOVE 0(A0,D1*2),D0 ; convert to planar value
RTS ; => all done
; TABLE TO MAP FROM 3 BIT RGB TO OLD-STYLE COLOR INDICES
MapTBL DC.W blackColor ; RBG = 0,0,0 -> black
DC.W blueColor ; RBG = 0,0,1 -> blue
DC.W greenColor ; RBG = 0,1,0 -> green
DC.W cyanColor ; RBG = 0,1,1 -> cyan
DC.W redColor ; RBG = 1,0,0 -> red
DC.W magentaColor ; RBG = 1,0,1 -> magenta
DC.W yellowColor ; RBG = 1,1,0 -> yellow
DC.W whiteColor ; RBG = 1,1,1 -> white
;---------------------------------------------------
;
; procedure RGBBackColor (Color : RGBColor);
;
; This routine takes an RGB triple and sets the current Graf- or CGrafPort
; fields so that drawing will take place with the best match of the
; requested color, using the current GDevice's color matching rules. The
; appropriate fields are set depending on portType.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBBackColor) (RGBBackColor)
RGBBackColor
MOVEQ #BKCOLOR,D0 ; get offset to the index field
MOVEQ #RGBBkColor,D1 ; get offset to RGB field
BRA SHARE ; => and use common code
;---------------------------------------------------
;
; procedure myNewCWindow()
;
; Initialize the palette manager fields of the new window.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewCWindow) (myNewCWindow)
myNewCWindow PROC EXPORT
ROMNewCWindow EQU $0F9F6 ; normal NewCWindow routine <PB302>
; shuffle parameters so it will return to us
MOVE.L SP,A0 ; get src for params
MOVE.L SP,A1 ; get dst for params
MOVE.L (A0)+,D1 ; save RTS
MOVEQ #7,D0 ; move 8 longs
@NxtLong MOVE.L (A0)+,(A1)+ ; move a long
DBRA D0,@NxtLong ; repeat for all longs
MOVE.L D1,30(SP) ; stuff original RTS
JSRROM ROMNewCWindow ; call NewCWindow <PB302>
; always set the default palette to 0
MOVE.L (SP),A1 ; get the window
MOVE.L GrafVars(A1),A0 ; get handle to vars
MOVE.L (A0),A0 ; point to vars
CLR.L PMFgColor(A0) ; and clear palette
MOVE.L (SP)+,A1 ; get window pointer
MOVE.L (SP),A0 ; get return address
MOVE.L A1,(SP) ; stuff wPtr
JMP (A0) ; and return
;---------------------------------------------------
;
; procedure myNewWindow();
;
; When NewWindow is called, do an ActivatePalette in case there's a default palette.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewWindow) (myNewWindow)
myNewWindow PROC EXPORT
ROMNewWindow EQU $0FA08 ; normal NewWindow routine <PB302>
; shuffle parameters so it will return to us
MOVE.L SP,A0 ; get src for params
MOVE.L SP,A1 ; get dst for params
MOVE.L (A0)+,D1 ; save RTS
MOVEQ #7,D0 ; move 8 longs
@NxtLong MOVE.L (A0)+,(A1)+ ; move a long
DBRA D0,@NxtLong ; repeat for all longs
MOVE.L D1,30(SP) ; stuff original RTS
JSRROM ROMNewWindow ; call NewWindow <PB302>
MOVE.L (SP),-(SP) ; push the window
_ActivatePalette ; and activate the system palette
@DONE MOVE.L (SP)+,A1 ; get window pointer
MOVE.L (SP),A0 ; get return address
MOVE.L A1,(SP) ; stuff wPtr
JMP (A0) ; and return
;---------------------------------------------------
;
; procedure HiliteWindow();
;
; Patch HiliteWindow to call ActivatePalette if called from SelectWindow
; AND if it is not called from MoveWindow!
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (HiliteWindow) (myHiliteWindow)
myHiliteWindow PROC EXPORT
FromSelect EQU $1016A ; RTS if called from select <PB302>
FromMove EQU $10396 ; RTS if selected from Move <PB302>
ROMHilite EQU $0FFCE ; real HiliteWindow <PB302>
CMPRA FromSelect,(SP) ; from selectWindow? <PB302>
BNE.S @JustHilite ; => no, just hilite
CMPRA FromMove,$38(SP) ; from Move? <PB302>
BEQ.S @JustHilite ; => yes, just hilite
TST.B 4(SP) ; hiliting?
BEQ.S @JustHilite ; => no, just (un)hilite
LEA 6(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE -(A0),-(SP) ; push boolean
JSRROM ROMHilite ; call hilite in ROM <PB302>
MOVE.L 6(SP),-(SP) ; push window pointer
_ActivatePalette ; and activate its palette
RTD #6 ; strip 6 bytes params and return
@JustHilite JMPROM ROMHilite ; and complete the call <PB302>
;---------------------------------------------------
;
; procedure MyMoveWindow
;
; Patch MoveWindow to call ActivatePalette
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MoveWindow) (myMoveWindow)
MyMoveWindow PROC EXPORT
ROMMove EQU $0FD9C ; real MoveWindow <PB302>
LEA 10(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE.L -(A0),-(SP) ; push dst location
MOVE -(A0),-(SP) ; push frontflag
JSRROM ROMMove ; call movewindow <PB302>
MOVE.L 10(SP),-(SP) ; push window
_ActivatePalette ; and activate its palette
RTD #10 ; strip 10 bytes and return
;---------------------------------------------------
;
; procedure MySizeWindow
;
; Patch SizeWindow to call MySetPalette
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SizeWindow) (mySizeWindow)
MySizeWindow PROC EXPORT
ROMSize EQU $1000E ; real SizeWindow <PB302>
LEA 10(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE.L -(A0),-(SP) ; push dst location
MOVE -(A0),-(SP) ; push frontflag
JSRROM ROMSize ; call SizeWindow <PB302>
MOVE.L 10(SP),-(SP) ; push window
_ActivatePalette ; and activate its palette
RTD #10 ; strip 10 bytes and return
;---------------------------------------------------
;
; procedure MyClose
;
; Patch CloseWindow to call DisposPalette. In the initial system disk release, this
; patch mistakenly operated on DisposeWindow instead of CloseWindow.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CloseWindow) (myClose)
MyClose PROC EXPORT
ROMClose EQU $0FB6E ; real CloseWindow <PB302>
MOVE.L 4(SP),A0 ; get the window
TST PORTBITS+ROWBYTES(A0) ; is it new?
BPL.S @NotNew ; => no
MOVE.L GrafVars(A0),A0 ; get grafVar handle
MOVE.L (A0),A0 ; point at grafVars
MOVE.L PmFgColor(A0),D0 ; is there a palette
BEQ.S @NotNew ; => no
Move.L D0,A0 ; let's use an address register AWC.PB457
Move.L (A0),A0 ; dereference it AWC.PB457
BTst #DisposeBit,pmPrivate(A0) ; should we dispose of it? AWC.PB457
Beq.S @NotNew ; no => the user has to dispose of it AWC.PB457
MOVE.L D0,-(SP) ; else push palette
_DisposePalette ; and dump it
@NotNew JMPROM ROMClose ; and dispose the window <PB302>
;---------------------------------------------------
;
; procedure MyShowHide();
;
; Patch MyShowHide to call ActivatePalette. If it is being called to show a hidden window,
; then do the ActivatePalette.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ShowHide) (myShowHide)
MyShowHide PROC EXPORT
ROMShow EQU $0F742 ; real MoveWindow <PB302>
TST.B 4(SP) ; is it show?
BEQ.S @NoShow ; =>no, no go show
MOVE.L 6(SP),A0 ; get the window
TST.B WVisible(A0) ; is it showtime
BNE.S @NoShow ; =>no, not yet
LEA 6(SP),A0 ; point to window
MOVE.L (A0),-(SP) ; push window
MOVE -(A0),-(SP) ; push marquis
JSRROM ROMShow ; call showwindow <PB302>
MOVE.L A1,-(SP) ; save A1 for ShowHide!
MOVE.L 10(SP),-(SP) ; push window
_ActivatePalette ; and activate its palette
MOVE.L (SP)+,A1 ; restore A1 for ShawHide
RTD #6 ; strip 10 bytes and return
@NoShow JMPROM ROMShow ; the ROM must begin <PB302>
;---------------------------------------------------
;
; procedure MyExit;
;
; Patch MyExit to call DisposePalette for all palettes in the app heap. In addition, jam
; theGDevice and srcDevice with MainDevice. As if that weren't enough, make sure that
; cursor interrupts are enabled.
;
; This patch is not installed by A/UX or under MultiFinder.
;
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MyExit) (myExit)
MyExit PROC EXPORT
EXPORT myExitExit ; address of JMP target to daisy chain <PB158>
ROMIAZInit EQU $4080DEF8 ; jump back into ROM
ROMAppZoneAddr EQU $4080D434 ; a useful routine
MOVEM.L A0-A3/D0-D3,-(SP) ; save all registers
MOVE.L PMgrHandle,A2 ; get paletteMgr handle
CMP.L MinusOne,A2 ; is it there?
BEQ.S 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
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 D1,D0 ; and get for routine
JSR ROMAppZoneAddr ; in application area (or zero)? <C699>
BNE.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
MOVE.L MainDevice,A0 ; get the main device
MOVE.L A0,SrcDevice ; set the src device
MOVE.L A0,theGDevice ; and the current device
MOVE #$2000,SR ; make sure interrupts enabled
MOVEM.L (SP)+,A0-A3/D0-D3 ; restore all registers
JMP $4080000A ; jump to next code in chain <PB158>
myExitExit EQU *-4 ; address of JMP target <PB158>
ENDIF ; end of patches commented out for ROM RWH.C864
; Okay, that's it. We're out of here!