;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 _SortPoints ; call Quickdraw sort routine 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 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 ; 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 Jsr Allocate ; yes => call allocation routine Bra.S CheckTolrnt ; do the tolerant entries QuickHandle Move myEntries(A6),D0 ; get the number of entries Move.L PalettePtr(A6),A0 ; get palette pointer Lea pmInfo(A0),A0 ; bump A0 to the first ColorInfo Bra.S QuickEnd ; jump into loop QuickLoop Tst ciFlags(A0) ; is it handled? Bmi.S NextQuick ; yes => continue BTst #AnimatedBit,ciFlags+1(A0) ; is it animating? Beq.S NextQuick ; no => leave it alone BSet #HandledBit,ciFlags(A0) ; mark it handled NextQuick AddA.L #ciSize,A0 ; bump A0 to the next ColorInfo QuickEnd DBra D0,QuickLoop ; continue for pmEntries 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 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 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 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 dstWindow equ ParamSize+8-4 ; target window dstEntry equ dstWindow-2 ; palette entry to animate 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 dstWindow equ ParamSize+8-4 ; window to animate 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 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.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 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 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, 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 ; 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 ; 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 ; 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 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 FromMove EQU $10396 ; RTS if selected from Move ROMHilite EQU $0FFCE ; real HiliteWindow CMPRA FromSelect,(SP) ; from selectWindow? BNE.S @JustHilite ; => no, just hilite CMPRA FromMove,$38(SP) ; from Move? 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 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 ;--------------------------------------------------- ; ; procedure MyMoveWindow ; ; Patch MoveWindow to call ActivatePalette ; ; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MoveWindow) (myMoveWindow) MyMoveWindow PROC EXPORT ROMMove EQU $0FD9C ; real MoveWindow 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 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 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 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 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 ;--------------------------------------------------- ; ; 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 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 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 ;--------------------------------------------------- ; ; 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 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)? 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 myExitExit EQU *-4 ; address of JMP target ENDIF ; end of patches commented out for ROM RWH.C864 ; Okay, that's it. We're out of here!