mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-06-01 07:41:58 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
3731 lines
160 KiB
Plaintext
3731 lines
160 KiB
Plaintext
;EASE$$$ READ ONLY COPY of file ÒPaletteMgrPatch.aÓ
|
||
; 1.0 BAL 11/19/1989 Changed name to avoid conflicts between system 6.0 and
|
||
; ROM/32-Bit QD versions.
|
||
; -- Revisions Of PaletteMgr.a Below --
|
||
; 1.5 SES 08/28/1989 Removed references to nFiles. Updated equates accordingly.
|
||
; 1.4 BAL 06/26/1989 dvb For 6.0.4 Moved grayrgn test into initpalettes, removed initmenus
|
||
; 1.3 BAL 06/12/1989 Altered patch to InitMenus to check grayRgn before calling _InitPalettes
|
||
;¥1.2 CEL 06/10/1989 Moved Private.a QuickDraw Equates into proper QuickDraw
|
||
; private file (colorequ.a), got rid of QuickDraw nFiles dependencies
|
||
; and fixed up necessary filesÉ
|
||
;¥1.1 CCH 11/16/1988 Updated to newest version.
|
||
;
|
||
;_______________________________________________________________________________________
|
||
; File: PaletteMgr.a
|
||
;
|
||
; Version 6.0.1
|
||
;
|
||
; Copyright 1987-1988 Apple Computer, Inc. All Rights Reserved
|
||
;
|
||
;_______________________________________________________________________________________
|
||
;
|
||
; modification history
|
||
;
|
||
; <02feb87> AWC new this date
|
||
; <26mar87> PB103 AWC non-window manager version completed
|
||
; <27mar87> AWC interface changed to support window manager
|
||
; <27mar87> EHB window manager calls added
|
||
; <29mar87> PB150 AWC fixed nil pointers (RGBForeColor) and added WindowCopy
|
||
; <30mar87> AWC/EHB background updates, ExitToShell fix, System Palette
|
||
; <30Mar87> JTC Daisy chain the IAZInit routine properly.
|
||
; <15Jul87> AWC/FJL SetPalette(Ptr(-1),...), Menu fix, update problems
|
||
; <20Jul87> PB212 DAF Removed GetNewCWindow portion of NewCWindow fix. Changed
|
||
; myDisposeWindow to fix CloseWindow.
|
||
; <22Jul87> PB221 AWC fix to crash when there are no menus (see note @PB225)
|
||
; <22Jul87> PB222 AWC CopyPalette implemented (see note @PB225)
|
||
; <22Jul87> PB223 AWC fix to bug causing too many updates (see note @PB225)
|
||
; <22Jul87> PB224 AWC added support for Juggler (see note @PB225)
|
||
; <22Jul87> PB225 AWC NewPWindow implemented; NOTE: fixes PB221 through PB225
|
||
; were all added at once. They are unique numbers solely
|
||
; for bureaucratic reasons.
|
||
; <12Aug87> C864 RWH Added ROMPaletteMgr Conditional flag (its defined outside this file
|
||
; in order to make Rom78Fix build work). Conditional-ed out calls
|
||
; at end of this file so it can be put in ROM. Search for ;!!!!!
|
||
; Made ReDrawMenuBar an RTS for the ROM version. Made the call to
|
||
; SortPoints use the macro from QDHooks.a.
|
||
; <01Sep87> PB259 AWC Fixed NewPWindow so it doesn't polymerize the stack.
|
||
; C872 Same as PB259
|
||
; <04Sep87> PB262 AWC Fixed ActivatePalette to generate fewer color updates
|
||
; C886 Same as PB262
|
||
; <16Nov87> PB302 AGH Made changes for use with A/UX toolbox.
|
||
; <01Feb88> PB377 AWC Fixed 5 minor bugs in the Palette Manager (1st entry bug, screen
|
||
; dev. bug, D0 error bugs, protection bits bugs, PmBackColor/explicit
|
||
; bug)
|
||
; <02Feb88> PB378 AWC Oops, I forgot one. The 16th palette causes a crash...
|
||
; <12Feb88> PB392 AWC Fixed a fix which short circuits the menu bar update code.
|
||
; <23Mar88> PB438 DAF Removed InitWindows fix, since it wasn't installed anyway.
|
||
; <24Mar88> PB439 AWC Fixed SetPalette; removed pmWindow references
|
||
; <07Apr88> PB457 AWC Fixed ColorMore crash, implemented AppPalette, DisposeBit
|
||
; <08Apr88> PB462 AWC Fixed lines out of order bug created in PB459
|
||
; <18Apr88> PB469 AWC Blocked InitGraf from using the system resource file
|
||
; <26Apr88> PB480 AWC Fixed PaletteMgr updates, animation of black, and set Palettes NoPurge
|
||
; <29Apr88> PB485 AWC Blocked spurious ActivatePalette's by checking wHilited
|
||
; <13Jun88> PB500 AWC Fixed AnimateEntry; made Palette Manager active even if
|
||
; no 'clut' devices are present
|
||
; <17Jun88> PB506 AWC Moved InitGraf fix to InitMenus; IAZNotify routine clears WindowList
|
||
; <22Jun88> PB508 AWC Added MenuBar updates and SingleFinder Desktop updates; made routines
|
||
; draw using the AppPalette; added DirtySeeds to correct update problem;
|
||
; blocked InitMenus from initializing AppPalette twice; now clear
|
||
; AppPalette in the event that its palette is disposed
|
||
; <27Jun88> PB520 AWC Save grafPort across PaintOne; put InitMenus stuff into InitPalettes;
|
||
; removed NewPWindow (which was never publicized); generally cleaned
|
||
; things up for the ROM version. Fixed unlocked handle in PmForeColor.
|
||
; <12Jul88> PB530 AWC Fixed CopyPalette resize problem; changed behavior of explicit
|
||
; colors on direct devices
|
||
;
|
||
;___________________________________________________________________________
|
||
|
||
XPalettes PROC EXPORT ; dummy procedure; return to globals AWC.PB457
|
||
ENDPROC ; AWC.PB457
|
||
|
||
AppPalette Equ $DCC ; low memory global for layer palette AWC.PB457
|
||
UpdateMask Equ $E000 ; bits used to record update flags in pmPrivate AWC.PB457
|
||
AllUpdates Equ $C000 ; combination of CForeBit and CBackBIt AWC.PB457
|
||
plttUpdates Equ $0002 ; value passed to SetPalette [short] AWC.PB457
|
||
|
||
; Here is what is left of the Patch Collator stuff. The Palette Manager routines have never
|
||
; been patches to the ROM - they were never in the original ROM, so there was nothing to
|
||
; patch. This is all there is. The window manager patches are shown below and are marked
|
||
; near the routine with another patch signal. To find one, double click on the Patch Name
|
||
; and search for that (Command-H under MPW 2.0).
|
||
;
|
||
; File Date Patch# PMgr Routines Trap#
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (InitPalettes) $AA90
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewPalette) $AA91
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetNewPalette) $AA92
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (DisposePalette) $AA93
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ActivatePalette) $AA94
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetPalette) $AA95
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetPalette) $AA96
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (PmForeColor) $AA97
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (PmBackColor) $AA98
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (AnimateEntry) $AA99
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (AnimatePalette) $AA9A
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetEntryColor) $AA9B
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetEntryColor) $AA9C
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (GetEntryUsage) $AA9D
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SetEntryUsage) $AA9E
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CTab2Palette) $AA9F
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (Palette2CTab) $AAA0
|
||
;AppleSystemPatch PaletteMgr.a 22Jul87 #PB222 (CopyPalette) $AAA1
|
||
;
|
||
; Fix File Date Patch# Fixed Routines Patch Routine Name
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBForeColor) (RGBForeColor)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBBackColor) (RGBBackColor)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB506 (InitMenus) (myInitMenus)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewCWindow) (myNewCWindow)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewWindow) (myNewWindow)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (HiliteWindow) (myHiliteWindow)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MoveWindow) (myMoveWindow)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SizeWindow) (mySizeWindow)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CloseWindow) (myClose)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ShowHide) (myShowHide)
|
||
;AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MyExit) (myExit)
|
||
;
|
||
; Another routine which must be included for proper Palette Manager operation is
|
||
; GetNewCWindow which is patched in PatchIIROM.a
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE InitPalettes; INLINE $AA90;
|
||
;
|
||
|
||
InitPalettes PROC EXPORT
|
||
IMPORT RecordPalette
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
|
||
|
||
moveq #-1,d0 ; get a useful value <1.3>
|
||
cmp.l grayRgn,d0 ; has it been initialized? <1.3>
|
||
beq goHome ; no, don't call the brinker <1.3>
|
||
|
||
|
||
; Start by running down the device list, finding all active CLUT devices. Count how many
|
||
; there are and record them in PListHandle.
|
||
|
||
Move.L PMgrHandle,D0 ; get the Palette Manager handle
|
||
Cmp.L #PMgrNil,D0 ; is it nil?
|
||
Bne ChkAppPltt ; we're initializaed - check for AppPalette AWC.PB520
|
||
|
||
; To start things up, allocate enough room for static Palette Manager data and 32 device table
|
||
; slots. Note that the current implementation of Color Quickdraw (not the architecture) sets
|
||
; a limit on the color index model of 256 entries. THIS NUMBER IS ASSUMED BY THE CODE BELOW,
|
||
; but the structure will allow modification once 'clut's bigger than 256 entries are allowed.
|
||
; This code also assumes that the cards have the potential of being 256 entry cards even if
|
||
; set at a lower resolution, so it always allocates 256 entries in each device map (integer sized).
|
||
|
||
; Note - the total space allocated for pm device table space is presumed (below) to
|
||
; be long word aligned. See the loop below at Clearing.
|
||
|
||
Move.L #PMgrDataSz,D4 ; set D4 to the required size AWC.PB500
|
||
Move.L D4,D0 ; copy size to D0
|
||
_NewHandle ,SYS,CLEAR ; allocate our data area in the system heap
|
||
Bne GoHome ; we got an error, so we quit
|
||
Move.L A0,A3 ; copy to A3 for later use
|
||
Move.L A0,PMgrHandle ; and remember it in low memory
|
||
MoveQ #0,D3 ; zero our device count
|
||
Move.L (A3),A4 ; dereference PMgrHandle
|
||
AddA #DevHandles,A4 ; point A4 at our local device list
|
||
Clr.L -(SP) ; push room for device handle AWC.PB500
|
||
_GetDeviceList ; get the start of the device list AWC.PB500
|
||
Move.L (SP)+,A2 ; put the device list in A2 AWC.PB500
|
||
Bra.S DeviceEnd ; jump to the end of the loop AWC.PB500
|
||
|
||
DeviceLoop Move.L (A2),A0 ; dereference device handle
|
||
Move gdFlags(A0),D0 ; get flags; is it an active device?
|
||
Bpl.S NextDevice ; no => examine next device
|
||
BTst #ScreenDevice,D0 ; is it a screen device?
|
||
Beq.S NextDevice ; no => examine next device AWC.PB377
|
||
Move gdType(A0),D0 ; get the type of the device AWC.PB377
|
||
Cmp #ClutType,D0 ; is it a Clut device?
|
||
Bne.S NextDevice ; no => we only track Clut devices
|
||
AddQ #1,D3 ; yes => bump our device count by 1
|
||
Move.L A2,DevHandle(A4) ; copy device handle AWC.PB500
|
||
Clr.L DevFrontMost(A4) ; clear device FrontMost field
|
||
AddQ #DevInfoSz,A4 ; bump A4 to the next device slot
|
||
Add.L #256*PmDevSz,D4 ; each device table is 1024 bytes (for now)
|
||
Cmp #DevLimit,D3 ; are we at the limit the PMgr can handle? AWC.PB500
|
||
Bpl.S EnoughDevs ; if so, we'll ignore any remaining devices
|
||
NextDevice Move.L gdNextGD(A0),A2 ; grab next device AWC.PB500
|
||
DeviceEnd Move.L A2,D0 ; CmpA #Nil,A2; is it nil? AWC.PB500
|
||
Bne.S DeviceLoop ; no => let's do it again
|
||
EnoughDevs Move.L (A3),A4 ; redereference PMgrHandle
|
||
Move D3,nDevs(A4) ; save length of device list
|
||
Move D3,D0 ; make a copy of D3
|
||
Bne.S SeedSizeOk ; make sure we have a minimum size seed AWC.PB500
|
||
AddQ #1,D0 ; a kludge, but it's easier this way AWC.PB500
|
||
SeedSizeOk Lsl #2,D0 ; multiply by 4 AWC.PB500
|
||
Move D0,SeedHSize(A4) ; save size of SeedHSize handle
|
||
Clr APalettes(A4) ; no animating palettes yet
|
||
Move #ListSpace,FreeSpaces(A4) ; 16 free slots; we'll add more if needed
|
||
Move.L D4,D0 ; D4 is the required size of PMgrHandle
|
||
Move.L A3,A0 ; put handle in A0 for the call
|
||
_SetHandleSize ; and expand the handle up
|
||
Bne.S ResizeFails ; it went badly
|
||
Move.L #ListSpace,D0 ; start with initial space for handles
|
||
Lsl #3,D0 ; multiply by 8
|
||
_NewHandle SYS,CLEAR ; allocate and clear the handle
|
||
Beq.S ClearAll ; if it works, continue
|
||
Move.L A3,A0 ; prepare to dispose the handle
|
||
_DisposHandle ; get rid of it
|
||
ResizeFails Move.L #PMgrNil,PMgrHandle ; it didn't work - zero the handle
|
||
Bra GoHome ; head home with error in D0 AWC.PB508
|
||
|
||
ClearAll Move.L (A3),A4 ; redereference PMgrHandle
|
||
Move.L A0,PListHandle(A4) ; save the list of handles
|
||
Move.L A3,A0 ; put PMgrHandle into A0
|
||
_HLock ; lock it down
|
||
Move D3,D0 ; get the number of devices
|
||
Lsl #8,D0 ; multiply by 1024/4 (1024 per device/4 per CLR.L)
|
||
Lea PMgrDataSz(A4),A0 ; calculate start of device links
|
||
Bra.S ClearEnd ; jump into loop
|
||
|
||
ClearLoop Clr.L (A0)+ ; clear a long word - see! long word aligned
|
||
ClearEnd DBra D0,ClearLoop ; repeat for all long words
|
||
|
||
Move.L theZone,-(SP) ; save the current zone
|
||
Move.L SysZone,theZone ; set the system zone
|
||
|
||
Clr.L -(SP) ; clear some space for a handle
|
||
Clr -(SP) ; push PaletteId = 0
|
||
_GetNewPalette ; try to get the system palette
|
||
Move.L (SP)+,SysPalette(A4) ; save it; was it nil?
|
||
Bne.S NoError ; no => we're done
|
||
|
||
Lea SysColors,A0 ; get a pointer to our default table
|
||
Move.L #17*8,D0 ; get size
|
||
_PtrToHand ; make a handle out of it
|
||
Move.L A0,D3 ; save it
|
||
|
||
Clr.L -(SP) ; space for result
|
||
Move #16,-(SP) ; push the number of entries
|
||
Move.L A0,-(SP) ; push our handle
|
||
Move #pmTolerant,-(SP) ; all tolerant entries
|
||
Move #$4000,-(SP) ; reasonably tolerant entries, too
|
||
_NewPalette ; let's call ourselves to get a new palette
|
||
Move.L (SP)+,SysPalette(A4) ; save the palette; we sure hope we got one
|
||
Move.L D3,A0 ; put handle back in A0
|
||
_DisposHandle ; snuff it
|
||
|
||
NoError Move.L SysPalette(A4),A0 ; get the palette for a moment
|
||
CmpA.L #Nil,A0 ; is there one?
|
||
Beq.S Cleanup ; no => cleanup
|
||
Move.L (A0),A0 ; dereference SysPalette
|
||
BSet #CForeBit,pmPrivate(A0) ; set the system update bits
|
||
BSet #CBackBit,PmPrivate(A0)
|
||
Cleanup Move.L (SP)+,theZone ; restore the current zone
|
||
Move.L A3,A0 ; get PMgrHandle
|
||
_HUnlock ; unlock it
|
||
Clr.L AppPalette ; clear the applications's palette AWC.PB457
|
||
Bra.S LookForIt ; jump ahead AWC.PB520
|
||
|
||
; Notice that we rely upon AppPalette being initialized (or -1) every time we arrive here. If
|
||
; it is non-zero, we assume this is an extra call to InitPalettes so we just leave.
|
||
|
||
ChkAppPltt Move.L AppPalette,D0 ; fetch AppPalette; is it nil? AWC.PB520
|
||
Beq.S LookForIt ; yes => look for a palette resource 0 AWC.PB508
|
||
AddQ.L #1,D0 ; bump it by 1; was it $FFFFFFFF? AWC.PB508
|
||
Bne.S GoHome ; no => must be good; abort AWC.PB520
|
||
Move.L D0,AppPalette ; clear the AppPalette AWC.PB508
|
||
LookForIt Tst CurApRefNum ; are we using the system resource file? AWC.PB469
|
||
Beq.S GoHome ; yes => forget installing an AppPalette AWC.PB520
|
||
Clr -(SP) ; function result AWC.PB457
|
||
_CurResFile ; get the current resfile AWC.PB457
|
||
Move (SP)+,D3 ; put it in D3 AWC.PB457
|
||
Cmp CurApRefNum,D3 ; need we change it? AWC.PB457
|
||
Beq.S ResFileOkay ; no => we've already got it AWC.PB457
|
||
Move CurApRefNum,-(SP) ; push the refnum back AWC.PB457
|
||
_UseResFile ; use this resfile AWC.PB457
|
||
Clr -(SP) ; result word AWC.PB506
|
||
_ResError ; see if this worked AWC.PB506
|
||
Move (SP)+,D0 ; get the result AWC.PB506
|
||
Bne.S GoHome ; quit if we didn't get it AWC.PB520
|
||
ResFileOkay Clr.L -(SP) ; function result AWC.PB457
|
||
Move.L #'pltt',-(SP) ; push the resource type AWC.PB457
|
||
Clr -(SP) ; id 0 AWC.PB457
|
||
_Get1Resource ; fetch an application palette, if any AWC.PB457
|
||
Move.L (SP)+,A2 ; get handle off the stack AWC.PB457
|
||
Move.L A2,D0 ; CmpA.L #Nil,A2; did we get a resource? AWC.PB457
|
||
Beq.S Cleanup2 ; if nil we go home AWC.PB457
|
||
Move.L A2,-(SP) ; push it for the DetachResource AWC.PB457
|
||
_DetachResource ; disconnect from resource manager AWC.PB457
|
||
Move.L (A2),A0 ; dereference palette AWC.PB457
|
||
Move #AllUpdates,D1 ; set D1 to the default AWC.PB457
|
||
Move plttUpdates(A0),D0 ; get update bits AWC.PB457
|
||
Bpl.S NoResUpdate ; the user didn't specify any AWC.PB457
|
||
Lsl #1,D0 ; put the bits in the correct place AWC.PB457
|
||
Move D0,D1 ; put the result into D1 AWC.PB457
|
||
NoResUpdate Move D1,pmPrivate(A0) ; put them in the correct place AWC.PB457
|
||
Move.L A2,-(SP) ; push palette for the RecordPalette AWC.PB457
|
||
Jsr RecordPalette ; allocates seeds handle, records palette AWC.PB457
|
||
Bne.S Cleanup2 ; it disposed palette if failed AWC.PB457
|
||
Move.L A2,AppPalette ; copy it to AppPalette AWC.PB457
|
||
Move.L (A2),A0 ; dereference AppPalette AWC.PB457
|
||
BSet #DisposeBit,pmPrivate(A0) ; set for automatic disposal AWC.PB457
|
||
Clr.L pmWindow(A0) ; clear the window field just for grins AWC.PB457
|
||
Clr.L pmDevices(A0) ; clear device bitmap AWC.PB457
|
||
Cleanup2 Cmp CurApRefNum,D3 ; did we change the current resfile? AWC.PB457
|
||
Beq.S GoHome ; no => don't put it back AWC.PB457
|
||
Move D3,-(SP) ; push the old current resfile AWC.PB457
|
||
_UseResFile ; and restore the old one AWC.PB457
|
||
GoHome MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rts ; go home
|
||
|
||
SysColors DC.W $0000,$0003,$0000,$000F ; seed [long], transIndex [word], ctSize [word]
|
||
DC.W $0000,$FFFF,$FFFF,$FFFF ; white
|
||
DC.W $0001,$0000,$0000,$0000 ; black
|
||
DC.W $0002,$C000,$C000,$C000 ; light gray
|
||
DC.W $0003,$8000,$8000,$8000 ; medium gray
|
||
DC.W $0004,$4000,$4000,$4000 ; dark gray
|
||
DC.W $0005,$DD6B,$08C2,$06A2 ; Apple red
|
||
DC.W $0006,$FFFF,$648A,$028C ; Apple orange
|
||
DC.W $0007,$FC00,$F37D,$052F ; Apple yellow
|
||
DC.W $0008,$1F21,$B793,$1431 ; Apple green
|
||
DC.W $0009,$0000,$0000,$D400 ; Apple blue
|
||
DC.W $000A,$46E3,$0000,$A53E ; Apple violet
|
||
DC.W $000B,$F2D7,$0856,$84EC ;
|
||
DC.W $000C,$90D7,$7160,$3A34 ;
|
||
DC.W $000D,$0241,$AB54,$EAFF ;
|
||
DC.W $000E,$0000,$64AF,$11B0 ;
|
||
DC.W $000F,$5600,$2C9D,$0524 ;
|
||
SysColorEnd
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE RecordPalette(myPalette: PaletteHandle); LOCAL;
|
||
;
|
||
; Copies myPalette into the PListHandle and records (in the pmPrivate field) where
|
||
; it lies in that list. If there are no free spaces in the PListHandle then that
|
||
; handle is resized. If it can't be resized, RecordPalette returns an error in D0.
|
||
; Otherwise a new handle is allocated for myPalette's pmSeeds field. If one can't
|
||
; be allocated, RecordPalette returns an error. It will also return an error if the
|
||
; PMgrHandle is nil. If RecordPalette returns an error, it first disposes of
|
||
; myPalette so the caller doesn't have to worry about watching the error code.
|
||
|
||
RecordPalette PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
myPalette equ ParamSize+8-4 ; source Palette handle
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3/A2-A4,-(SP) ; save registers
|
||
|
||
Move.L myPalette(A6),A4 ; get my palette first in case we branch to Error
|
||
Move.L PMgrHandle,A2 ; get the PMgrHandle
|
||
CmpA.L #PMgrNil,A2 ; has it been initialized?
|
||
Beq Error ; no => handle the error (.S won't reach)
|
||
Move.L (A2),A0 ; dereference the PMgrHandle
|
||
Move.L PListHandle(A0),A3 ; get the handle to the list of palettes
|
||
MoveQ #0,D0 ; clear high word
|
||
Move SeedHSize(A0),D0 ; get length of seeds handles
|
||
_NewHandle ,CLEAR ; allocate it; did we succeed?
|
||
Bne Error ; no => handle the error (.S won't reach)
|
||
|
||
Move.L (A4),A1 ; dereference myPalette
|
||
Move.L A0,pmSeeds(A1) ; store the seeds handle in it
|
||
|
||
Move.L (A2),A1 ; redereference the PMgrHandle
|
||
Move FreeSpaces(A1),D0 ; get number of free slots; are any left?
|
||
Bne.S FindOne ; yes => don't resize it; search for a free one
|
||
|
||
MoveQ #0,D3 ; clear high word
|
||
Move APalettes(A1),D3 ; get current size
|
||
Move.L D3,D0 ; copy it
|
||
Add #ListSpace,D0 ; bump it to add more room
|
||
Bmi.S Error ; return an error if it wraps
|
||
Lsl.L #3,D0 ; multiply by 8
|
||
Move.L A3,A0 ; copy PListHandle to A0
|
||
_SetHandleSize ; resize it
|
||
Bne.S Error ; we couldn't do it
|
||
|
||
; Now we have to clear all of the new entries we just created.
|
||
|
||
Move.L A3,A0 ; get PListHandle
|
||
Move.L (A0),A0 ; redereference this
|
||
Lea (A0,D3.W*8),A0 ; point us at the block to clear
|
||
Move.L #ListSpace,D0 ; get how many entries to clear
|
||
Bra.S ClearEnd ; jump into loop
|
||
|
||
ClearLoop Clr.L (A0)+ ; clear the Palette field
|
||
Clr.L (A0)+ ; clear the animation field
|
||
ClearEnd DBra D0,ClearLoop ; loop for ListSpace entries
|
||
|
||
AddQ #1,D3 ; D3 is palette's position in PListHandle
|
||
Move.L (A3),A0 ; dereference PListHandle
|
||
Lea (A0,D3.W*8),A0 ; point A0 at the current position
|
||
Move.L (A2),A1 ; redereference the PMgrHandle
|
||
Move #ListSpace-1,FreeSpaces(A1) ; number of spaces we've added AWC.PB378
|
||
Bra.S Cleanup ; share common code
|
||
|
||
; We have a free one somewhere in the list. Search forwards until we find one we can use.
|
||
; A1 is still pointing at the dereferenced PMgrHandle.
|
||
|
||
FindOne Move APalettes(A1),D0 ; get number of active handles
|
||
Add FreeSpaces(A1),D0 ; calculate total number of entries
|
||
MoveQ #0,D3 ; initialize our counter
|
||
Move.L (A3),A0 ; dereference PListHandle
|
||
Bra.S FindEnd ; jump into loop
|
||
|
||
FindLoop Move.L PaletteRef(A0),D1 ; get first entry
|
||
Beq.S FoundIt ; we've got one
|
||
AddQ #PLstEntrySz,A0 ; bump to the next entry
|
||
AddQ #1,D3 ; bump our counter
|
||
FindEnd DBra D0,FindLoop ; repeat for all spaces
|
||
Bra.S Error ; this should not happen
|
||
|
||
; when we reach this section of common code, A1 = PMgrHandle^, D3 is the position of
|
||
; the palette, and A0 points to PListHandle^^[D3]
|
||
|
||
FoundIt SubQ #1,FreeSpaces(A1) ; decrement the number free
|
||
Cleanup AddQ #1,APalettes(A1) ; bump the number used
|
||
|
||
Move.L A4,PaletteRef(A0) ; record the palette handle in PListHandle
|
||
Clr.L Reserves(A0) ; clear the number of entries it reserves
|
||
|
||
Move.L (A4),A0 ; dereference the Palette
|
||
Move pmPrivate(A0),D0 ; grab the current update values AWC.PB457
|
||
And #UpdateMask,D0 ; clear away all but the update bits AWC.PB457
|
||
Or D0,D3 ; OR palette number with the update bits AWC.PB457
|
||
Move D3,pmPrivate(A0) ; this is the number of the palette
|
||
MoveQ #0,D0 ; no error
|
||
Bra.S GoHome ; we're done-oh!
|
||
|
||
Error Move.L A4,A0 ; get Palette handle
|
||
_DisposHandle ; get rid of it
|
||
MoveQ #1,D0 ; set an error
|
||
GoHome Tst.L D0 ; set condition codes for return
|
||
MoveM.L (SP)+,D3/A2-A4 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; FUNCTION NewPalette(entries: INTEGER; srcColors: CTabHandle; srcUsage,srcTolerance:
|
||
; INTEGER) : PaletteHandle; INLINE $AA91;
|
||
;
|
||
; Allocate a new palette and fill it with information from myColors. Set the usage
|
||
; field of each ciInfo to myUsage and set the tolerance to myTolerance. If myColors
|
||
; is nil we initialize all the colors to black.
|
||
|
||
NewPalette FUNC EXPORT
|
||
|
||
ParamSize equ 10 ; total bytes of params
|
||
Palette equ ParamSize+12-4 ; function result
|
||
entries equ Palette-2 ; number of entries in Palette
|
||
srcColors equ entries-4 ; Color table handle
|
||
srcUsage equ srcColors-2 ; default usage for each color in Palette
|
||
srcTolerance equ srcUsage-2 ; default tolerance for each color in Palette
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3/A2,-(SP) ; save registers
|
||
Clr.L Palette(A6) ; set the result to nil
|
||
Move entries(A6),D3 ; fetch number of entries
|
||
MoveQ #0,D0 ; clear it out
|
||
Move D3,D0 ; copy it for a calculation
|
||
AddQ #1,D0 ; add one for the header
|
||
Lsl.L #4,D0 ; multiply by 16
|
||
_NewHandle ,CLEAR ; get the handle; did we get an error?
|
||
Bne.S GoHome ; yes => we're done for
|
||
Move.L A0,A2 ; no => save the handle
|
||
Move.L A2,-(SP) ; push handle
|
||
Jsr RecordPalette ; allocates a seed's handle and records palette
|
||
Bne.S GoHome ; it disposed the palette handle if it failed
|
||
|
||
; A2 contains the handle to the new Palette. Return the handle, then start by dereferencing it.
|
||
; For now we'll just clear everything. Note that we're making use of the fact that
|
||
; the size of the header is the same as an entry itself, so we can fall straight
|
||
; into the DBra and expect it to clear Entries+1 records! Also, zero the window field
|
||
; so we know that this palette is floating
|
||
|
||
Move.L A2,Palette(A6) ; return the result
|
||
Move.L (A2),A0 ; dereference Palette handle
|
||
Move D3,pmEntries(A0) ; copy pmEntries
|
||
Clr.L pmWindow(A0) ; zero the window field
|
||
|
||
Move D3,D0 ; get entries into D0
|
||
Move srcUsage(A6),D1 ; copy usage to D1
|
||
Swap D1 ; put usage into high word
|
||
Move srcTolerance(A6),D1 ; put tolerance into low word
|
||
Lea pmInfo+ciUsage(A0),A0 ; point A0 at first ColorInfo
|
||
Bra.S EntryEnd ; jump into the loop
|
||
|
||
EntryLoop Move.L D1,(A0) ; set ciUsage (high word) and ciTolerance (low word)
|
||
AddA #ciSize,A0 ; bump A0 to the next ciUsage field
|
||
EntryEnd Dbra D0,EntryLoop ; loop for all entries
|
||
|
||
Move.L srcColors(A6),A1 ; get ctabhandle
|
||
CmpA.L #Nil,A1 ; is it nil?
|
||
Beq.S NoCTab ; yes => skip the copy
|
||
Move.L (A1),A1 ; dereference the source color table
|
||
Move ctSize(A1),D0 ; get last color table entry
|
||
AddQ #1,D0 ; make it number of entries; is it >= 1?
|
||
Ble.S NoCTab ; no => we're done
|
||
|
||
Move.L (A2),A0 ; redereference PaletteHandle
|
||
AddA.L #pmInfo+ciRGB+red,A0 ; bump A0 to pmInfo.ciRGB.red
|
||
AddA.L #ctTable+rgb+red,A1 ; bump A1 to ctTable.red
|
||
|
||
; put min(ctSize+1,pmEntries) into D0
|
||
|
||
Cmp D0,D3 ; compare color table size to palette size
|
||
Bge.S UseAsIs ; if D0 is less than D3, we'll use it as is
|
||
Move D3,D0 ; copy the lower value into D0
|
||
UseAsIs MoveQ #0,D1 ; D1 points at this entry
|
||
Bra.S CopyEnd ; jump into loop
|
||
|
||
CopyLoop Move.L red(A1),red(A0) ; copy red and green
|
||
Move blue(A1),blue(A0) ; copy blue
|
||
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
|
||
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
|
||
CopyEnd Dbra D0,CopyLoop ; loop until the copy is complete
|
||
|
||
NoCTab MoveQ #0,D0 ; no error
|
||
GoHome MoveM.L (SP)+,D3/A2 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; FUNCTION GetNewPalette(paletteID: INTEGER) : PaletteHandle; INLINE $AA92;
|
||
;
|
||
; GetNewPalette gets a resource of type 'pltt' with the specified ID and clears
|
||
; all the private fields. It then returns the data structure as a PaletteHandle.
|
||
;
|
||
|
||
GetNewPalette FUNC EXPORT
|
||
|
||
ParamSize equ 2 ; total bytes of params
|
||
Palette equ ParamSize+12-4 ; function result
|
||
paletteID equ Palette-2 ; number of entries in Palette
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Move.L A2,-(SP) ; save registers
|
||
Clr.L Palette(A6) ; set result to Nil
|
||
|
||
; Load the data and detach it from resource manager
|
||
|
||
Clr.L -(SP) ; make space for result
|
||
Move.L #'pltt',-(SP) ; push resource type
|
||
Move paletteID(A6),-(SP) ; push resource ID
|
||
_GetResource ; get the resource
|
||
Move.L (SP)+,D1 ; get handle off the stack
|
||
Beq.S GoHome ; if nil we go home
|
||
Move.L D1,A2 ; copy it to A2
|
||
Move.L D1,-(SP) ; push it back on the stack
|
||
_DetachResource ; disconnect from resource manager
|
||
|
||
Move.L A2,A0 ; copy it for the HNoPurge AWC.PB480
|
||
_HNoPurge ; we can't handle purged palettes AWC.PB480
|
||
Tst D0 ; did it return an error? AWC.PB480
|
||
Bne.S GoHome ; yes => go home AWC.PB480
|
||
|
||
Move.L (A2),A0 ; dereference palette AWC.PB457
|
||
Move #AllUpdates,D1 ; set D1 to the default AWC.PB457
|
||
Move plttUpdates(A0),D0 ; get update bits AWC.PB457
|
||
Bpl.S NoResUpdate ; the user didn't specify any AWC.PB457
|
||
Lsl #1,D0 ; put the bits in the correct place AWC.PB457
|
||
Move D0,D1 ; put the result into D1 AWC.PB457
|
||
NoResUpdate Move D1,pmPrivate(A0) ; put them in the correct place AWC.PB457
|
||
Move.L A2,-(SP) ; push the handle
|
||
Jsr RecordPalette ; allocates a seeds handle and records palette
|
||
Bne.S GoHome ; it disposed the palette handle if it failed
|
||
Move.L A2,Palette(A6) ; save Palette in result space
|
||
|
||
; clear the window field and also the private fields
|
||
|
||
Move.L (A2),A2 ; dereference it
|
||
Clr.L pmWindow(A2) ; set window field; this palette floats
|
||
Clr.L pmDevices(A2) ; clear device bitmap
|
||
|
||
GoHome Move.L (SP)+,A2 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE ClearPalette(cPalette: PaletteHandle); LOCAL;
|
||
;
|
||
|
||
ClearPalette PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
cPalette equ ParamSize+8-4 ; source Palette handle
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D2-D3/A2-A4,-(SP) ; save registers
|
||
|
||
Move.L PMgrHandle,A3 ; get palette manager handle
|
||
CmpA.L #PMgrNil,A3 ; are we initialized?
|
||
Beq GoHome ; no => quit AWC.PB377
|
||
Move.L (A3),A3 ; dereference it
|
||
|
||
Move.L cPalette(A6),A1 ; get palette handle AWC.PB457
|
||
Move.L (A1),A2 ; dereference it AWC.PB457
|
||
|
||
; Examine and remember the number of reserves this palette still has. Clear the number.
|
||
|
||
Move pmPrivate(A2),D0 ; get the number of this palette
|
||
And #PIdMask,D0 ; clear away update bits
|
||
Move.L PListHandle(A3),A0 ; get the palette list handle
|
||
Move.L (A0),A0 ; dereference it
|
||
CmpA.L PaletteRef(A0,D0.W*8),A1 ; is this the correct handle? AWC.PB462
|
||
Bne BadPalette ; no => don't dispose anything AWC.PB462
|
||
Move Reserves(A0,D0.W*8),D3 ; remember how many animating entries it has
|
||
Clr.L Reserves(A0,D0.W*8) ; clear the count
|
||
|
||
; Now clear each of the seeds this palette knows about, so that we'll update if we
|
||
; become active again.
|
||
|
||
Clr.L pmDevices(A2) ; clear devices field
|
||
Move.L pmSeeds(A2),A0 ; get seeds handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move SeedHSize(A3),D0 ; get size of handle
|
||
Lsr #2,D0 ; divide by 4
|
||
Bra.S SeedEnd ; start clear loop
|
||
|
||
SeedLoop Clr.L (A0)+ ; clear the remembered seed
|
||
SeedEnd DBra D0,SeedLoop ; do it again
|
||
MoveQ #0,D0 ; no error
|
||
|
||
; Now check to see if we have any animating entries which we can dispose
|
||
|
||
Tst D3 ; were there any animating entries?
|
||
Beq.S GoHome ; no => quit
|
||
|
||
; run through every color to make sure it is not reserving any entries on any device
|
||
; by examining what the PaletteManager has to say about this palette as well as what
|
||
; each entry's ciPrivate field has to say about the subject. Leave pmPrivate field
|
||
; (which tells PMgr which palette we ought to be) alone.
|
||
|
||
Move pmEntries(A2),D0 ; get number of entries
|
||
AddA.L #pmInfo,A2 ; bump A2 to the first ColorInfo
|
||
Lea DevHandles(A3),A4 ; point A4 at PMgrDevices
|
||
AddA.L #LinkTabs,A3 ; point A3 to LinkTabs
|
||
Bra.S EntryEnd ; jump into loop
|
||
|
||
EntryLoop Move ciPrivate(A2),D3 ; get the current link information
|
||
Bpl.S NextEntry ; if positive it's not a link
|
||
|
||
NextLink BfExtU D3{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D3{24:8},D2 ; grab index number (0..255)
|
||
Move.L DevHandle(A4,D1.W*8),A0 ; get the device handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap
|
||
Move.L (A0),A0 ; dereference pixmap
|
||
Move.L pmTable(A0),A0 ; get handle to CTab
|
||
Move.L A0,DevCTab(A6) ; save color table handle, too
|
||
Move.L (A0),A0 ; dereference CTab
|
||
Cmp ctSize(A0),D2 ; is index number <= entries - 1?
|
||
Bhi.S IgnoreIt ; no => don't unreserve it
|
||
Clr ctTable+value(A0,D2.W*8) ; unreserve it
|
||
IgnoreIt Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Lea (A3,D1.L*4),A0 ; point A0 at next forward link
|
||
Move ForeLink(A0),D3 ; get next link
|
||
Clr.L ForeLink(A0) ; clear it for the next guy
|
||
Tst D3 ; is there another link to examine?
|
||
Bmi.S NextLink ; yes => go unlink it
|
||
NextEntry Clr ciFlags(A2) ; shut down any crap
|
||
Clr.L ciPrivate(A2) ; clear it
|
||
AddA.L #ciSize,A2 ; bump A0 to the next ColorInfo
|
||
EntryEnd DBra D0,EntryLoop ; loop for all pmEntries
|
||
GoHome MoveQ #0,D0 ; clear error condition
|
||
BadPalette MoveM.L (SP)+,D2-D3/A2-A4 ; restore registers AWC.PB457
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE ErasePalette(ePalette: PaletteHandle); LOCAL;
|
||
;
|
||
|
||
ErasePalette PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
ePalette equ ParamSize+8-4 ; PaletteHandle to dispose
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L A2-A3,-(SP) ; save registers
|
||
|
||
Move.L ePalette(A6),A3 ; get the handle
|
||
Move.L (A3),A2 ; dereference it
|
||
Move.L pmSeeds(A2),A0 ; get the seeds handle while we have it
|
||
CmpA #Nil,A0 ; is it nil?
|
||
Beq.S DontDispose ; yes => punt
|
||
_DisposHandle ; it's gone
|
||
DontDispose Move.L WindowList,A0 ; get the window list for this layer AWC.PB506
|
||
Bra.S ListLoop ; continue AWC.PB439
|
||
|
||
CheckWindow Tst PortBits+Rowbytes(A0) ; by chance is it an old window? AWC.PB439
|
||
Bpl.S IgnoreWind ; yes => ignore it AWC.PB439
|
||
Move.L GrafVars(A0),A1 ; get GrafVars handle AWC.PB439
|
||
Move.L (A1),A1 ; dereference it AWC.PB439
|
||
Move.L PmFgColor(A1),D0 ; get the palette AWC.PB439
|
||
Cmp.L ePalette(A6),D0 ; is it correct? AWC.PB439
|
||
Bne.S IgnoreWind ; no => don't clear it AWC.PB439
|
||
Clr.L PmFgColor(A1) ; mark the window as Paletteless AWC.PB439
|
||
IgnoreWind Move.L nextWindow(A0),A0 ; grab the next window AWC.PB439
|
||
ListLoop Move.L A0,D0 ; CmpA.L #Nil,A0; another window? AWC.PB439
|
||
Bne.S CheckWindow ; yes => keep looking AWC.PB439
|
||
|
||
CmpA.L AppPalette,A3 ; are we disposing AppPalette? AWC.PB508
|
||
Bne.S NotAppPltt ; no => whew! AWC.PB508
|
||
Clr.L AppPalette ; okay, we won't try to find it anymore AWC.PB508
|
||
|
||
NotAppPltt Move pmPrivate(A2),D0 ; grab the last field we need from A2 AWC.PB439
|
||
And #PIdMask,D0 ; clear away flag bits
|
||
Move.L PMgrHandle,A2 ; get the main handle
|
||
CmpA.L #PMgrNil,A2 ; is it nil?
|
||
Beq.S GoHome ; yes => don't try to find it
|
||
Move.L (A2),A2 ; dereference it
|
||
Move APalettes(A2),D1 ; start with number of active palettes
|
||
Add FreeSpaces(A2),D1 ; add free spaces to get length of list
|
||
Cmp D1,D0 ; are we within the correct range?
|
||
Bpl.S GoHome ; no => punt
|
||
|
||
Move.L PListHandle(A2),A1 ; get handle to list of palettes
|
||
Move.L (A1),A1 ; dereference it
|
||
|
||
CmpA.L (A1,D0.W*8),A3 ; get this handle; do they match?
|
||
Bne.S GoHome ; no => in the future we may scan for it; for now, punt
|
||
Clr.L (A1,D0.W*8) ; it's no longer referenced
|
||
AddQ #1,FreeSpaces(A2) ; add 1 to free spaces
|
||
SubQ #1,APalettes(A2) ; subtract 1 from total palettes
|
||
GoHome MoveM.L (SP)+,A2-A3 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE DisposePalette(srcPalette: PaletteHandle); INLINE $AA93;
|
||
;
|
||
|
||
DisposePalette PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
srcPalette equ ParamSize+8-4 ; PaletteHandle to dispose
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Move.L A2,-(SP) ; save register
|
||
Move.L srcPalette(A6),A2 ; get the handle
|
||
CmpA.L #Nil,A2 ; is it nil?
|
||
Beq.S GoHome ; yes => go home
|
||
Move.L A2,-(SP) ; push handle
|
||
Jsr ClearPalette ; release any animating entries
|
||
Bne.S GoHome ; if nonzero the palette was bad AWC.PB457
|
||
Move.L A2,-(SP) ; push it again
|
||
Jsr ErasePalette ; erase palette from PMgrHandle and its window
|
||
Move.L A2,A0 ; fetch palette handle into A0
|
||
_DisposHandle
|
||
GoHome Move.L (SP)+,A2 ; restore register
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------;
|
||
; ;
|
||
; Here begins a number of routines called by ;
|
||
; ActivatePalette. These routines share its ;
|
||
; stack frame built on A6, building their own ;
|
||
; stack frames on A4. ;
|
||
; ;
|
||
;---------------------------------------------------;
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; FUNCTION FindLink(LinkInfo:integer):integer; LOCAL;
|
||
;
|
||
; FindLink searches the device links until it encounters a device that matches Device or
|
||
; until it reaches the end of the list. It returns the index if it finds one. It
|
||
; returns 0 (which is an illegal index since it matches white) if it can't find one.
|
||
|
||
FindLink PROC EXPORT
|
||
|
||
ParamSize equ 2 ; total bytes of params
|
||
theIndex equ ParamSize+10-2 ; index result
|
||
LinkInfo equ theIndex-2 ; this palette's key to previously reserved entries
|
||
|
||
VarSize equ 0
|
||
|
||
Link A4,#VarSize ; build stack frame
|
||
Move.L D3,-(SP) ; save a register
|
||
|
||
; We will use D3 as a watchdog counter. We set it to the maximum number of devices that we
|
||
; might have to search so that if things go very wrong we stand a chance of finding out about it.
|
||
|
||
Clr theIndex(A4) ; set result to "illegal"
|
||
Move LinkInfo(A4),D0 ; get link data
|
||
BfExtU D0{16:3},D1 ; grab top 3 bits
|
||
Cmp #4,D1 ; are they set correctly
|
||
Bne.S GoHome ; no => the LinkInfo is invalid
|
||
Move Devices(A6),D3 ; get number of devices
|
||
Move.L PMgrPtr(A6),A0 ; PMgrHandle^
|
||
AddA.L #LinkTabs,A0 ; calculate start of LinkTabs
|
||
Bra.S IndexEnd ; start watchdog loop
|
||
|
||
IndexLoop BfExtU D0{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D0{24:8},D2 ; grab index number (0..255)
|
||
Cmp CurDevice(A6),D1 ; is it this device?
|
||
Beq.S FoundIt ; yes => we've got it
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Move (A0,D1.L*4),D0 ; get next link; is the top bit set?
|
||
Bpl.S GoHome ; no => stop because we ran out of tries
|
||
IndexEnd DBra D3,IndexLoop ; examine another index until our watchdog runs out
|
||
|
||
; Our watchdog counter ran out, so something is terribly wrong. We'll be polite about it and
|
||
; say we were just unable to find it.
|
||
|
||
Bra.S GoHome
|
||
|
||
; We found the index. Set true and return the appropriate index to theIndex(A4)
|
||
|
||
FoundIt And #$00FF,D2 ; clear everything except the index
|
||
Move D2,theIndex(A4) ; set the result
|
||
GoHome Move.L (SP)+,D3 ; restore registers
|
||
Unlk A4 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE AnalyzeDev; LOCAL;
|
||
;
|
||
|
||
AnalyzeDev PROC EXPORT
|
||
|
||
MoveM.L D3-D6/A2-A3,-(SP) ; save registers
|
||
|
||
Move DevIndexes(A6),D0 ; get number of device entries
|
||
MoveQ #0,D1 ; clear high word, put starting index in low word
|
||
Move.L InfoPtr(A6),A3 ; get pointer to scratch area
|
||
Bra.S ClearEnd ; jump into loop
|
||
|
||
ClearLoop Move.L D1,(A3)+ ; clear high word, put index in low word
|
||
AddQ #1,D1 ; bump D1 to the next index
|
||
ClearEnd DBra D0,ClearLoop ; continue for the entire Histogram
|
||
Clr Histogram(A6)
|
||
|
||
Move.L PMgrPtr(A6),A2 ; put PMgrHandle^ into A2
|
||
Move APalettes(A2),D3 ; get number of active palettes
|
||
Cmp #1,D3 ; is there just the one?
|
||
Ble.S GoHome ; yes => we're done
|
||
Add FreeSpaces(A2),D3 ; make D3 the total space count
|
||
Move.L InfoPtr(A6),A3 ; point A3 at beginning of Histogram
|
||
Move.L PListHandle(A2),A0 ; get PListHandle (locked down)
|
||
Move.L (A0),D5 ; save pointer to next PaletteHandle in D5
|
||
Move CurDevice(A6),D6 ; put current device into D4
|
||
Bra.S HistoEnd ; jump into loop
|
||
|
||
HistoLoop Move.L D5,A0 ; get next palette
|
||
AddQ.L #PLstEntrySz,D5 ; bump D5 to next palette
|
||
MoveA.L (A0),A0 ; get next palette into A0
|
||
CmpA.L #Nil,A0 ; is this a free space?
|
||
Beq.S HistoEnd ; yes => go examine another one
|
||
CmpA.L PaletteH(A6),A0 ; is it the current palette?
|
||
Beq.S HistoEnd ; yes => go examine another one
|
||
Move.L (A0),A0 ; dereference the palette
|
||
Move.L pmDevices(A0),D0 ; get devices
|
||
BTst D6,D0 ; is it using this device?
|
||
Beq.S HistoEnd ; no => go examine another palette
|
||
Move pmEntries(A0),D4 ; get number of palette entries
|
||
Lea pmInfo(A0),A2 ; put first ColorInfo into A2 where we can keep it
|
||
Bra.S PaletteEnd ; jump into loop
|
||
|
||
PaletteLoop Clr.L -(SP) ; push space for result
|
||
Pea ciRGB(A2) ; push address of current color
|
||
_Color2Index ; get best fit
|
||
Move.L (SP)+,D0 ; pull the index
|
||
AddQ #1,HistCount(A3,D0.W*4) ; add to histogram reference count for this index
|
||
Bpl.S NotNegative ; a safeguard
|
||
SubQ #1,HistCount(A3,D0.W*4) ; put it back positive
|
||
NotNegative AddA.L #ciSize,A2 ; bump A2 to the next ColorInfo
|
||
PaletteEnd DBra D4,PaletteLoop ; continue for all pmEntries
|
||
HistoEnd DBra D3,HistoLoop ; continue for all palettes
|
||
|
||
; well you may have wondered what's going on here. We now have an array of reference
|
||
; counts for all palettes that use this device. Each index was allowed a longint of
|
||
; space, though, and the index itself was placed in the low word of that longint during
|
||
; initialization. If we view this combination as a "point" we can use the Quickdraw
|
||
; procedure "SortPoints" to do all the sorting work for us. It uses a stack-based
|
||
; non-recursive QuickSort algorithm. The reference count in the high word is the main
|
||
; key. If two of them happen to match, we won't much worry about the fact that secondary
|
||
; sorting occurs on the index itself. However, the sort will move the indexes around, too,
|
||
; so we'll end up with a sorted list of indexes with low reference counts at the beginning
|
||
; of the list. We've taken pains to make sure we have no negative reference counts, though
|
||
; that probably wasn't necessary.
|
||
|
||
Move.L A3,-(SP) ; push address of "points"
|
||
Move DevIndexes(A6),-(SP) ; push number of points
|
||
; Jsr ([SortPoints]) ; call Quickdraw sort routine <C864>
|
||
_SortPoints ; call Quickdraw sort routine <C864>
|
||
GoHome MoveM.L (SP)+,D3-D6/A2-A3 ; restore registers
|
||
Rts ; go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; Function Pillage:Integer; LOCAL;
|
||
;
|
||
|
||
Pillage PROC EXPORT
|
||
|
||
ParamSize equ 0 ; total bytes of params
|
||
EntryResult equ ParamSize+10-2 ; best index we can find
|
||
|
||
VarSize equ 0
|
||
|
||
Link A4,#VarSize ; build stack frame
|
||
MoveM.L D3/D4,-(SP) ; save registers
|
||
|
||
Clr EntryResult(A4) ; clear the result to illegal
|
||
Move.L DevCTab(A6),A1 ; get pointer to device color table
|
||
Move.L (A1),A1 ; dereference it
|
||
AddA.L #ctTable,A1 ; bump A1 to the first ColorSpec
|
||
Move DevIndexes(A6),D3 ; get number of indexes
|
||
Bra.S PillageEnd ; jump int the loop
|
||
|
||
PillageLoop BTst #5,value(A1,D3.W*8) ; is this one available for pillaging?
|
||
Bne.S PillageIt ; yes => go pillage it
|
||
PillageEnd DBra D3,PillageLoop ; continue for DevIndexes entries
|
||
Bra GoHome ; quit in utter failure!
|
||
|
||
PillageIt BfClr value(A1,D3.W*8){0:3} ; unprotected, unreserved, pillaged
|
||
SubQ #1,Pillages(A6) ; one less worth pillaging
|
||
Move D3,EntryResult(A4) ; return the pillaged index
|
||
|
||
; Now, what fun! We get to fix up all the device links!
|
||
|
||
Move CurDevice(A6),D0 ; get current device
|
||
Lsl #8,D0 ; multiply by table size/4
|
||
Add D3,D0 ; add in entry offset
|
||
Move.L PMgrPtr(A6),A0 ; get base pointer
|
||
AddA.L #LinkTabs,A0 ; bump base pointer to start of LinkTabs
|
||
Move ForeLink(A0,D0.W*4),D3 ; get forward links
|
||
Move BackLink(A0,D0.W*4),D4 ; get forward links
|
||
Clr.L (A0,D0.W*4) ; clear the links away
|
||
Tst D3 ; examine forward link
|
||
Bmi.S MultiLinks1 ; if < 0 we have more than one assigned
|
||
Tst D4 ; examine backward link
|
||
Bmi.S MultiLinks2 ; if < 0 we have more than one assigned
|
||
|
||
; This was a quickie. D3 contains the palette number, D4 the entry number. All we
|
||
; need do is tell the palette it no longer has it.
|
||
|
||
And #$1FFF,D3 ; clear key bits
|
||
Move.L PListPtr(A6),A0 ; get the palette list
|
||
SubQ #1,Reserves(A0,D3*8) ; it has one less entry reserved
|
||
Move.L PaletteRef(A0,D3*8),A0 ; get the palette
|
||
Move.L (A0),A0 ; dereference it
|
||
And.L #$00001FFF,D4 ; clear high word and key bits
|
||
Lsl.L #4,D4 ; make it an offset to the ColorInfo
|
||
Clr.L pmInfo+ciPrivate(A0,D4.L) ; clear the link
|
||
Bra GoHome ; we did it!
|
||
|
||
; The forward link goes somewhere. See if the backward one does too. If so,
|
||
; jump to BothLinks.
|
||
|
||
MultiLinks1 Tst D4 ; examine backward link
|
||
Bmi.S BothLinks ; both of them go somewhere
|
||
|
||
; The forward link goes somewhere, but the backward one does not. We must remember
|
||
; the first forward link so we can copy it into the palette, then we advance
|
||
; forward by one, copy the palette entry into that, and continue searching until we find
|
||
; out what palette this is.
|
||
|
||
Move D3,D0 ; remember the forward link
|
||
BfExtU D3{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D3{24:8},D2 ; grab index number (0..255)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Lea (A0,D1.L*4),A1 ; point A1 at next forward link
|
||
Move D4,BackLink(A1) ; copy the back link
|
||
Move ForeLink(A1),D3 ; get next link
|
||
Bpl.S GotPalette1 ; if > 0, we've found the palette
|
||
MultiFLoop BfExtU D3{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D3{24:8},D2 ; grab index number (0..255)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Move ForeLink(A0,D1.L*4),D3 ; get next link; is it positive?
|
||
Bmi.S MultiFLoop ; no => continue
|
||
|
||
GotPalette1 And #$1FFF,D3 ; clear key bits
|
||
Move.L PListPtr(A6),A0 ; get the palette list
|
||
SubQ #1,Reserves(A0,D3*8) ; it has one less entry reserved
|
||
Move.L PaletteRef(A0,D3*8),A0 ; get the palette
|
||
Move.L (A0),A0 ; dereference it
|
||
And.L #$00001FFF,D4 ; clear high word of entry
|
||
Lsl.L #4,D4 ; make it an offset to the ColorInfo
|
||
Move D0,pmInfo+ciPrivate(A0,D4.L) ; set a new link
|
||
Bra.S GoHome ; we did it!
|
||
|
||
; The backward link goes somewhere, but the forward one does not. We must advance
|
||
; backward by one, copy the palette id into it, and continue searching until we find out
|
||
; what palette this is.
|
||
|
||
MultiLinks2 BfExtU D4{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D4{24:8},D2 ; grab index number (0..255)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Lea (A0,D1.L*4),A1 ; point A1 at next backward link
|
||
Move D3,ForeLink(A1) ; copy the forward link
|
||
Move BackLink(A1),D4 ; get next link
|
||
Bpl.S GotPalette2 ; if > 0, we've found the palette
|
||
MultiBLoop BfExtU D4{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D4{24:8},D2 ; grab index number (0..255)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Move BackLink(A0,D1.L*4),D4 ; get next link; is it positive?
|
||
Bmi.S MultiBLoop ; no => continue
|
||
Bra.S GotPalette2 ; share common code
|
||
|
||
; We're in the middle of the list somewhere. We'll step one backward and copy
|
||
; the forelink from the current entry, then we'll step one foreward and copy
|
||
; the backlink from the current entry. Then we'll keep going forward until we
|
||
; find the palette. All we need do is decrement its reference count, so we don't
|
||
; need the entry number.
|
||
|
||
BothLinks BfExtU D4{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D4{24:8},D2 ; grab index number (0..255)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Lea (A0,D1.L*4),A1 ; point A1 at next backward link
|
||
Move D3,ForeLink(A1) ; copy the forward link
|
||
|
||
BfExtU D3{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D3{24:8},D2 ; grab index number (0..255)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Lea (A0,D1.L*4),A1 ; point A1 at next foreward link
|
||
Move D4,BackLink(A1) ; copy the backward link
|
||
Move ForeLink(A1),D3 ; get next foreward link
|
||
Bpl.S GotPalette2 ; if > 0, we've found the palette
|
||
|
||
BothLoop BfExtU D3{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D3{24:8},D2 ; grab index number (0..255)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Move ForeLink(A0,D1.L*4),D3 ; grab next forward link
|
||
Bmi.S BothLoop ; if < 0, we keep looking
|
||
|
||
GotPalette2 Move.L PListPtr(A6),A0 ; get the palette list
|
||
And #$1FFF,D3 ; clear away key bits
|
||
SubQ #1,Reserves(A0,D3*8) ; it has one less entry reserved
|
||
GoHome MoveM.L (SP)+,D3/D4 ; restore registers
|
||
Unlk A4 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE ReserveColor(myEntry:integer); LOCAL;
|
||
;
|
||
|
||
ReserveColor PROC EXPORT
|
||
|
||
ParamSize equ 2 ; total bytes of params
|
||
myEntry equ ParamSize+8-2 ; number of ColorInfo to reserve
|
||
|
||
VarSize equ 0
|
||
|
||
Link A4,#VarSize ; build stack frame
|
||
Move Histogram(A6),D0 ; get next entry to examine
|
||
Move DevIndexes(A6),D1 ; get number of indexes for this device
|
||
Sub D0,D1 ; calculate number of possibilites left
|
||
Ble.S NoneLeft ; none => quit, leaving color unhandled
|
||
Move.L InfoPtr(A6),A0 ; get pointer to histogram
|
||
Move.L DevCTab(A6),A1 ; get device CTabHandle
|
||
Move.L (A1),A1 ; dereference it
|
||
AddQ.L #ctTable,A1 ; bump it to the first ColorSpec
|
||
Bra.S CheckEnd ; jump into the loop
|
||
|
||
CheckLoop Move HistIndex(A0,D0.W*4),D2 ; get the next index
|
||
AddQ #1,D0 ; bump Histogram to next entry
|
||
Tst D2 ; is it "white"?
|
||
Beq.S CheckEnd ; yes => ignore it
|
||
Cmp BlackIndex(A6),D2 ; is it "black"?
|
||
Beq.S CheckEnd ; yes => ignore it
|
||
BTst #reserveBit,value(A1,D2.W*8); is this entry reserved? <1.5>
|
||
Beq.S FoundOne ; no => we've got it!
|
||
CheckEnd DBra D1,CheckLoop ; continue for all remaining indexes
|
||
|
||
; We've used all available unreserved entries. Now we look to see if we can pillage
|
||
; anything from the device table.
|
||
|
||
NoneLeft Move D0,Histogram(A6) ; mark Histogram as done
|
||
Tst Pillages(A6) ; is there anything to pillage?
|
||
Beq GoHome ; no => quit
|
||
Clr -(SP) ; function result
|
||
Jsr Pillage ; get an entry by pillaging
|
||
Move.L DevCTab(A6),A1 ; restore A1 AWC.PB480
|
||
Move.L (A1),A1 ; dereference it AWC.PB480
|
||
AddQ.L #ctTable,A1 ; bump it to the first ColorSpec AWC.PB480
|
||
Move (SP)+,D2 ; put it in D2; is it legal?
|
||
Bne.S TakeEntry ; yes => roust it out
|
||
Bra GoHome ; no => miserable failure
|
||
|
||
FoundOne Move D0,Histogram(A6) ; mark used portion of Histogram
|
||
TakeEntry Move.L PalettePtr(A6),A0 ; get palette pointer
|
||
MoveQ #0,D0 ; clear high word
|
||
Move myEntry(A4),D0 ; get entry number
|
||
Lsl.L #4,D0 ; calculate offset to ColorInfo
|
||
Lea pmInfo(A0,D0.L),A0 ; point A0 at ColorInfo
|
||
BSet #HandledBit,ciFlags(A0) ; mark this entry as handled
|
||
Move.L ciRGB+red(A0),RGB+red(A1,D2.W*8) ; update red and green
|
||
Move ciRGB+blue(A0),RGB+blue(A1,D2.W*8) ; update blue
|
||
AddQ #1,Updates(A6) ; we've changed something
|
||
BSet #reserveBit,value(A1,D2.W*8) ; reserve it <1.5>
|
||
|
||
; For old or new links, the BackLink will still point at the entry number | $6000
|
||
|
||
Move.L DevLinks(A6),A1 ; point A1 at LinkTab
|
||
Move myEntry(A4),D0 ; grab entry number
|
||
And #$7FFF,D0 ; ensure that the top bit is off
|
||
Or #$6000,D0 ; set the top bits to 011
|
||
Move D0,BackLink(A1,D2.W*4) ; set backward link to entry | $6000
|
||
|
||
; Calculate a link to this new guy in D0. This will go in ciPrivate and, if we already
|
||
; had a link, into the BackLink of the old guy.
|
||
|
||
Move CurDevice(A6),D0 ; get current device again
|
||
Lsl #8,D0 ; shift device into upper byte
|
||
Or D2,D0 ; OR in the device number
|
||
BSet #15,D0 ; set the three highest bits to 100
|
||
|
||
; Copy the old link then set the new one. Then look to see if the old link was real.
|
||
; If so, we have some work to do. If not, initialize the link by setting the forelink
|
||
; to the palette number. The back link has already been set to the entry number.
|
||
|
||
Move ciPrivate(A0),D1 ; copy the old link
|
||
Move D0,ciPrivate(A0) ; point ciPrivate at the new guy
|
||
Tst D1 ; did we have any old links?
|
||
Bne.S OldLinks ; yes => relink it
|
||
|
||
Move.L PalettePtr(A6),A0 ; get pointer to palette
|
||
Move pmPrivate(A0),D0 ; grab number of this palette
|
||
And #PIdMask,D0 ; clear the flag bits
|
||
Or #$6000,D0 ; to make it non-zero, set the top bits to 011
|
||
Move D0,ForeLink(A1,D2.W*4) ; set forward link to palette | $6000
|
||
Bra.S FixRefCount ; fix up the palette
|
||
|
||
OldLinks Move D1,ForeLink(A1,D2.W*4) ; point Dev[FoundIndex] at old ciPrivate
|
||
BfExtU D1{24:8},D2 ; grab index number (0..255)
|
||
BfExtU D1{19:5},D1 ; grab device number (0..31)
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Move.L PMgrPtr(A6),A1 ; get base pointer
|
||
AddA.L #LinkTabs,A1 ; bump it to the LinkTabs
|
||
Move D0,BackLink(A1,D1.L*4) ; set the backward link
|
||
FixRefCount Move.L PListPtr(A6),A0 ; get PListPtr
|
||
Move.L PalettePtr(A6),A1 ; get palette
|
||
Move pmPrivate(A1),D0 ; get palette number
|
||
And #PIdMask,D0 ; clear the flag bits
|
||
AddQ #1,Reserves(A0,D0.W*8) ; bump number of reserves
|
||
GoHome Unlk A4 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE Allocate; LOCAL;
|
||
;
|
||
|
||
Allocate PROC EXPORT
|
||
|
||
; We have one or more animating entries. For each entry in myPalette, look to see if it is
|
||
; animating. If so, look to see if it exists on this device. If not, look to see if we can
|
||
; allocate it on this device.
|
||
|
||
MoveM.L D3/D4/A2,-(SP) ; save registers
|
||
Jsr AnalyzeDev ; analyze the entries used on the device
|
||
Move.L PalettePtr(A6),A2 ; get palette pointer
|
||
Move pmEntries(A2),D3 ; get number of entries
|
||
MoveQ #0,D4 ; D4 is the entry number
|
||
AddA.L #pmInfo,A2 ; bump A2 to the first ColorInfo
|
||
Bra.S AnimateEnd ; jump into loop
|
||
|
||
AnimateLoop Move ciFlags(A2),D0 ; examine "handled"
|
||
Bmi.S NextAnimate ; it was explicit or courteous; ignore it
|
||
BTst #AnimatedBit,D0 ; are we animating?
|
||
Beq.S NextAnimate ; no => ignore it
|
||
Clr -(SP) ; clear index result
|
||
Move ciPrivate(A2),-(SP) ; push animation link info (first word only)
|
||
Jsr FindLink ; FindLink(Device,myPalette^^.pmInfo[i].ciPrivate)
|
||
Move (SP)+,D0 ; pop the index result
|
||
Bne.S GotEntry ; true => it's still there - mark it as "handled"
|
||
|
||
; We will be allocating an entry for animation. If this is the first allocation, call
|
||
; AnalyzeDev to fill the scratch handle with the histogram for this device.
|
||
|
||
Move D4,-(SP) ; push entry number
|
||
Jsr ReserveColor ; try to reserve it
|
||
|
||
BTst #HandledBit,ciFlags(A2) ; did it succeed?
|
||
Bne.S NextAnimate ; yes => keep trying
|
||
Clr Tolerators(A6) ; don't bother with tolerators
|
||
Bra.S GoHome ; and go home
|
||
|
||
GotEntry BSet #HandledBit,ciFlags(A2) ; set "handled" bit
|
||
NextAnimate AddA.L #ciSize,A2 ; bump us to the next ColorInfo
|
||
AddQ #1,D4 ; bump entry number
|
||
AnimateEnd DBra D3,AnimateLoop ; loop for all pmEntries
|
||
|
||
GoHome MoveM.L (SP)+,D3/D4/A2 ; restore registers
|
||
Rts ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; FUNCTION DeltaRGB(ColorInfo,ColorSpec:Ptr):integer; LOCAL;
|
||
;
|
||
|
||
DeltaRGB FUNC EXPORT
|
||
|
||
ParamSize equ 8 ; total bytes of params
|
||
|
||
Delta equ ParamSIze+10-2 ; integer result
|
||
RGB1 equ Delta-4 ; palette entry pointer
|
||
RGB2 equ RGB1-4 ; color table entry pointer
|
||
|
||
VarSize equ 0 ; size of variables
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
|
||
Move.L RGB1(A6),A0 ; get first RGBColor
|
||
Move.L RGB2(A6),A1 ; get second RGBColor
|
||
|
||
Move (A1)+,D0 ; grab index red
|
||
Sub (A0)+,D0 ; subtract entry red
|
||
Bhs.S NotNeg1 ; take abs(Index.Red-ColorInfo.Red)
|
||
Neg D0 ; negate it
|
||
NotNeg1 Move (A1)+,D1 ; grab index green
|
||
Sub (A0)+,D1 ; subtract entry green
|
||
Bhs.S NotNeg2 ; take abs(Index.Green-ColorInfo.Green)
|
||
Neg D1 ; negate it
|
||
NotNeg2 Cmp D0,D1 ; leave greater unsigned value in D0
|
||
Blo.S DontSwitch1 ; D1 < D0 => D0 is already greater
|
||
Move D1,D0 ; green value is greater
|
||
DontSwitch1 Move (A1),D1 ; grab index blue
|
||
Sub (A0),D1 ; subtract entry blue
|
||
Bhs.S NotNeg3 ; take abs(Index.Blue-ColorInfo.Blue)
|
||
Neg D1 ; negate it
|
||
NotNeg3 Cmp D0,D1 ; leave greater unsigned value in D0
|
||
Blo.S FixResult ; D1 < D0 => D0 is already greater
|
||
Move D1,D0 ; blue value is greater
|
||
FixResult Move D0,Delta(A6) ; set result
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
ENDF
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE Correlate; LOCAL;
|
||
;
|
||
; This function uses the stack frame built upon A6 and builds its own stack frame on A4.
|
||
|
||
Correlate PROC EXPORT
|
||
|
||
ParamSize equ 0 ; total bytes of params
|
||
|
||
MoveM.L D3-D7/A2-A4,-(SP) ; save registers
|
||
|
||
; The InfoHandle is actually twice as large as we need, so we can just clear half of it
|
||
; without worrying about boundary conditions. We do, however, assume that DevIndexes is
|
||
; a multiple of 2.
|
||
|
||
Move.L InfoPtr(A6),A0 ; get pointer to scratch area
|
||
Move DevIndexes(A6),D0 ; maximum number of device indexes
|
||
Lsr #1,D0 ; divide by 2 because we clear longs
|
||
Bra.S ZeroEnd ; jump into the DBra
|
||
|
||
ZeroLoop Clr.L (A0)+ ; clear two palette reference fields
|
||
ZeroEnd DBra D0,ZeroLoop ; loop for half of all indexes
|
||
|
||
; The ciPrivate longint is used as a record containing two distinct fields. The first
|
||
; is in the high word and is reserved for the best index we can find. The low word is
|
||
; used to hold the DeltaRGB value for that index.
|
||
;
|
||
; A2 - points to pmInfo
|
||
; A3 - points to DevCTab^^.ctTable
|
||
; A4 - points to device scratch table
|
||
;
|
||
; D3 - keeps track of number of entries left to examine
|
||
; D4 - keeps track of offset to current ColorInfo
|
||
; D5 - holds best index and offset to colliding ColorInfo
|
||
; D6 - holds number of available device entries
|
||
; D7 - hold index of current ColorInfo
|
||
|
||
Move myEntries(A6),D3 ; get number of palette entries
|
||
Move.L PalettePtr(A6),A2 ; get pointer to palette
|
||
Lea pmInfo(A2),A2 ; bump A2 to first ColorInfo
|
||
Move.L DevCTab(A6),A0 ; get device color table handle
|
||
_HLock ; lock it down
|
||
Move.L (A0),A3 ; dereference it and copy it to A4
|
||
AddQ.L #ctTable,A3 ; bump it to the first ColorSpec
|
||
|
||
Move.L InfoPtr(A6),A4 ; get pointer to our info table, freshly zeroed
|
||
MoveQ #0,D4 ; initialize D4 to first ColorInfo in palette
|
||
MoveQ #0,D7 ; initialize D7 to 0
|
||
Clr Collisions(A6) ; clear number of collisions
|
||
Move Regulators(A6),D6 ; D6 holds number of available entries
|
||
Bra AllocEnd ; jump into loop that initializes tree (no .S)
|
||
|
||
AllocLoop Move ciFlags(A2,D4.L),D1 ; grab flags; is the HandledBit set? ( < 0 )
|
||
Bmi Chosen ; yes => we've done it already
|
||
BTst #TolerantBit,D1 ; no => are we tolerating?
|
||
Beq Chosen ; no => continue
|
||
Tst D6 ; have we run out of entry space?
|
||
Bgt.S NotYet ; no => keep going
|
||
Tst Pillages(A6) ; is there an entry to pillage?
|
||
Beq.S HandleIt ; no => we can punt
|
||
Clr -(SP) ; function result
|
||
Jsr Pillage ; we'll pillage so we'll have another color
|
||
Move (SP)+,D5 ; get the result
|
||
Bra.S Pillaged ; share common code
|
||
|
||
NotYet SubQ #1,D6 ; one more available entry consumed
|
||
Clr.L -(SP) ; push longint result
|
||
Pea ciRGB(A2,D4.L) ; push address of RGBColor field
|
||
_Color2Index ; find the best match for this color
|
||
Move.L (SP)+,D5 ; get best index
|
||
|
||
Pillaged Clr -(SP) ; push DeltaRGB result
|
||
Pea ciRGB(A2,D4.L) ; push the address of the ColorInfo.ciRGB
|
||
Pea RGB(A3,D5.W*8) ; push address of index's RGBColor
|
||
Jsr DeltaRGB ; calculate and set ciPrivate+2=color distance
|
||
Move (SP)+,D0 ; fetch distance
|
||
|
||
Tst D5 ; was the index white?
|
||
Beq.S CheckWhite ; yes => see if white is okay
|
||
Cmp BlackIndex(A6),D5 ; was the index black?
|
||
Bne.S NotBlack ; no => continue
|
||
|
||
; we have matched white or black. If we're within tolerance we'll mark this color as
|
||
; handled and continue. If not, we'll skip trying to pick the best entry stuff. We add
|
||
; 1 to D6 because we know we subtracted 1 at NotYet above and didn't mean to. We should
|
||
; never get here with a pillaged entry since black or white are never supposed to be
|
||
; reserved and therefore should never be pillaged. So, it should be safe to add one
|
||
; back to D6.
|
||
|
||
CheckWhite Cmp ciTolerance(A2,D4.L),D0 ; are we within tolerance?
|
||
Bls.S BlackWhite ; yes => mark these as handled
|
||
Clr.L ciPrivate(A2,D4.L) ; clear ColorInfo.ciPrivate field
|
||
AddQ #1,Collisions(A6) ; bump number of collisions
|
||
Bra.S Chosen ; share common code
|
||
|
||
BlackWhite AddQ #1,D6 ; don't count black or white
|
||
HandleIt BSet #HandledBit,ciFlags(A2,D4.L) ; set the handled bit
|
||
Bra.S Chosen ; share common code
|
||
|
||
NotBlack Lea (A4,D5.W*2),A1 ; point A1 at the DevTab entry for this index
|
||
MoveQ #0,D1 ; clear high word
|
||
Move (A1),D1 ; is there an entry here already (<> 0)
|
||
Beq.S PickCurrent ; no => mark the current entry as chosen
|
||
|
||
; We have a collision. The index to which we just matched is already used. Look
|
||
; to see which of the two entries has the lower DeltaRGB.
|
||
|
||
And #$7FFF,D1 ; clear away the "taken" bit AWC.PB377
|
||
AddQ #1,Collisions(A6) ; bump number of collisions
|
||
Lsl.L #4,D1 ; convert D1 to an offset to its ColorInfo
|
||
Move ciPrivate+2(A2,D1.L),D2 ; get tolerance of colliding entry
|
||
Cmp D0,D2 ; which unsigned value is lower?
|
||
Bhi.S SwapEntries ; current value => swap them PB262/C886
|
||
Clr.L ciPrivate(A2,D4.L) ; clear current index
|
||
Bra.S Chosen ; share common code
|
||
|
||
SwapEntries Clr.L ciPrivate(A2,D1.L) ; mark former entry index as unassigned
|
||
PickCurrent Move D5,ciPrivate(A2,D4.L) ; set index of current ColorInfo
|
||
Move D0,ciPrivate+2(A2,D4.L) ; set tolerance of current ColorInfo
|
||
Move D7,(A1) ; put it in the device index table
|
||
BSet #7,(A1) ; mark it as taken AWC.PB377
|
||
Chosen Add.L #ciSize,D4 ; bump D4 to offset of next ColorInfo
|
||
AddQ #1,D7 ; bump D7 to next ColorInfo
|
||
AllocEnd DBra D3,AllocLoop ; loop for all pmEntries
|
||
|
||
Tst Collisions(A6) ; have we any more work to do
|
||
Beq.S SetColors ; no => go examine tolerances
|
||
|
||
; STAGE 2 - make sure jumping to SetColors is warranted - notice we still look for
|
||
; unresolved colors the way it is currently written.
|
||
|
||
; In this section we try to find a unique index for each entry in the color table. We start
|
||
; by examining each index in the device for the reserved bit. If it is reserved we enter
|
||
; a value in our dev table so we won't try to match with it (we enter black's index). We
|
||
; run down the palette and find each entry which is a) not handled, b) tolerant, and
|
||
; c) unassigned (ciPrivate field is 0, white). Then we search the available colors one
|
||
; by one, finding the best match among the ones left by using DeltaRGB.
|
||
|
||
; A3 - points to DevCTab^^.ctTable
|
||
; A4 - points to device scratch table
|
||
; D0 - keeps track of number of ColorSpecs left to examine
|
||
; D1 - holds value of BlackIndex, used to mark indexes as reserved
|
||
|
||
Move DevIndexes(A6),D0 ; number of entries to mark
|
||
Move BlackIndex(A6),D1 ; mark entries as taken using "black"
|
||
Bra.S MarkEnd ; jump into loop
|
||
MarkLoop BTst #reserveBit,value(A3,D0.W*8); is this entry reserved? <1.5>
|
||
Beq.S MarkEnd ; no => continue
|
||
Move D1,(A4,D0.W*2) ; mark it as reserved in device info list
|
||
MarkEnd DBra D0,MarkLoop ; continue
|
||
|
||
Move D1,(A4) ; mark white as taken
|
||
Move D1,(A4,D1.W*2) ; mark black as taken
|
||
|
||
; A2 - points to current ColorInfo
|
||
; A3 - still points to DevCTab^^.ctTable
|
||
; D0 - used as a temp
|
||
; D3 - keeps track of number of entries left to examine
|
||
|
||
SetColors Move myEntries(A6),D3 ; potential number of entries to resolve
|
||
MoveQ #0,D4 ; ColorInfo entry counter
|
||
Bra ResolveEnd ; jump into loop
|
||
|
||
; By the time we reach this point a ColorInfo is either Tolerant or Handled.
|
||
|
||
ResolveLoop Tst ciFlags(A2) ; has this ColorInfo been handled?
|
||
Bmi NextCInfo ; yes => continue (.S won't fit)
|
||
Tst ciPrivate(A2) ; have we assigned an index yet?
|
||
Bne.S Resolved ; yes => continue
|
||
|
||
; Resolve this entry by searching for the best match from the available indexes
|
||
|
||
Move.L InfoPtr(A6),A1 ; get device info pointer
|
||
MoveQ #0,D0 ; clear entry counter
|
||
Move DevIndexes(A6),D1 ; get number of device entries
|
||
Move #$FFFF,ciPrivate+2(A2) ; set fit to worst
|
||
Bra.S FindEnd ; start loop
|
||
|
||
FindLoop Tst (A1,D0.W*2) ; is this index available?
|
||
Bne.S NextGuy ; no => try the next guy
|
||
MoveM.L D0-D1/A1,-(SP) ; save the current registers
|
||
Clr -(SP) ; push DeltaRGB result
|
||
Pea ciRGB(A2) ; push the address of the ColorInfo.ciRGB
|
||
Pea RGB(A3,D0.W*8) ; push address of index's RGBColor
|
||
Jsr DeltaRGB ; calculate and set ciPrivate+2=color distance
|
||
Move (SP)+,D0 ; fetch the distance
|
||
Tst ciPrivate(A2) ; have we anything yet?
|
||
Beq.S StuffIt ; no => use it
|
||
Cmp ciPrivate+2(A2),D0 ; is it closer or equal to what we last had?
|
||
Bhs.S NotBetter ; no => continue
|
||
StuffIt Move D0,ciPrivate+2(A2) ; remember better fit
|
||
MoveM.L (SP)+,D0-D1/A1 ; restore registers
|
||
Move D0,ciPrivate(A2) ; remember better index
|
||
Bra.S NextGuy ; continue
|
||
|
||
NotBetter MoveM.L (SP)+,D0-D1/A1 ; restore registers
|
||
NextGuy AddQ #1,D0
|
||
FindEnd DBra D1,FindLoop
|
||
Move ciPrivate(A2),D0 ; get best index
|
||
|
||
; if the result is 0 we've not found it, and we have a system error. While it would be
|
||
; good to find this, it's better to do something "robust" for a released version, so we'll
|
||
; jump ahead to GoodEnough and avoid any updates.
|
||
|
||
Beq.S GoodEnough ; internal palette manager error; leave quietly
|
||
; MoveQ #1,D0 ; clear the index <AWC>
|
||
FoundIt Move D0,ciPrivate(A2) ; shove the index into the field
|
||
Move #1,(A1,D0.W*2) ; mark dev info list as being taken
|
||
|
||
Clr -(SP) ; push DeltaRGB result
|
||
Pea ciRGB(A2) ; push the address of the ColorInfo.ciRGB
|
||
Move ciPrivate(A2),D0 ; fetch the entry we just assigned
|
||
Pea RGB(A3,D0.W*8) ; push address of index's RGBColor
|
||
Jsr DeltaRGB ; calculate and set ciPrivate+2=color distance
|
||
Move (SP)+,ciPrivate+2(A2) ; fetch distance
|
||
Resolved Move ciTolerance(A2),D0 ; get preferred tolerance
|
||
Cmp ciPrivate+2(A2),D0 ; is the unsigned current fit good enough?
|
||
Bhs.S GoodEnough ; yes => leave it alone
|
||
Move ciPrivate(A2),D0 ; get the index
|
||
Move.L ciRGB+red(A2),RGB+red(A3,D0.W*8) ; copy red and green to device CTab
|
||
Move ciRGB+blue(A2),RGB+blue(A3,D0.W*8) ; copy blue to device CTab
|
||
AddQ #1,Updates(A6) ; remember we've done one
|
||
GoodEnough Clr.L ciPrivate(A2) ; to keep everybody honest
|
||
NextCInfo Clr ciFlags(A2) ; we're all done with ciFlags
|
||
AddA.L #ciSize,A2 ; bump to the next ColorInfo
|
||
ResolveEnd DBra D3,ResolveLoop ; loop for all pmEntries
|
||
|
||
NoTolerant Move.L DevCTab(A6),A0 ; get handle to device color table
|
||
_HUnlock ; unlock it
|
||
|
||
MoveM.L (SP)+,D3-D7/A2-A4 ; restore registers
|
||
Rts ; strip parameters and go home
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE RedrawDesktop; LOCAL;
|
||
;
|
||
|
||
RedrawDesktop PROC EXPORT
|
||
|
||
Tst GrayRgnPrep(A6) ; have we set up the GrayRgn stuff? AWC.PB508
|
||
Bmi NoColorDesk ; yes => but there's nothing to do AWC.PB508
|
||
Bne.S DrawDesktop ; yes => skip the setup AWC.PB508
|
||
Move #-1,GrayRgnPrep(A6) ; initialize it to "nothing to do" AWC.PB508
|
||
Tst.B pCDeskPat ; test bit 7 of pCDeskPat AWC.PB508
|
||
Bpl.S NoColorDesk ; don't update the desktop AWC.PB508
|
||
Move.L DeskCPat,D0 ; is there a desktop pattern? AWC.PB508
|
||
Beq.S NoColorDesk ; no => don't update the desktop AWC.PB508
|
||
Move.L D0,A0 ; put the desktop pattern into A0 AWC.PB508
|
||
Move.L (A0),A0 ; dereference it AWC.PB508
|
||
Move.L PatMap(A0),A0 ; get the pixmaphandle AWC.PB508
|
||
Move.L (A0),A0 ; dereference it AWC.PB508
|
||
Move.L pmTable(A0),A0 ; get the CTabHandle AWC.PB508
|
||
Move.L (A0),A0 ; dereference it AWC.PB508
|
||
Move ctSize(A0),D1 ; get the size AWC.PB508
|
||
AddQ #1,D1 ; adjust it so the DBra works correctly AWC.PB508
|
||
AddA.L #ctTable+rgb,A0 ; bump A0 to first color spec AWC.PB508
|
||
Bra.S DeskEnd ; check for not black or white AWC.PB508
|
||
|
||
DeskLoop Move.L (A0)+,D2 ; get first AWC.PB508
|
||
Bne.S NotBlack ; not black; check white AWC.PB508
|
||
Move (A0)+,D2 ; get blue component AWC.PB508
|
||
Bne.S ColorDesk ; not black or white; do an update AWC.PB508
|
||
Bra.S DeskNext ; continue AWC.PB508
|
||
|
||
NotBlack Cmp.L #-1,D2 ; is it white? AWC.PB508
|
||
Bne.S ColorDesk ; not white; do an update AWC.PB508
|
||
Move (A0)+,D2 ; get blue component AWC.PB508
|
||
Cmp #-1,D2 ; is it white? AWC.PB508
|
||
Bne.S ColorDesk ; not white; do an update AWC.PB508
|
||
DeskNext AddQ.L #2,A0 ; bump A0 to next color AWC.PB508
|
||
DeskEnd DBra D1,DeskLoop ; continue AWC.PB508
|
||
Bra.S NoColorDesk ; nothing but black or white; skip it AWC.PB508
|
||
|
||
ColorDesk Clr.L -(SP) ; function result AWC.PB508
|
||
_NewRgn ; get a new region AWC.PB508
|
||
Move.L (SP)+,DeskRgn(A6) ; save it for later use; was it nil? AWC.PB508
|
||
Beq.S NoColorDesk ; yes => can't redraw anything AWC.PB508
|
||
Move #1,GrayRgnPrep(A6) ; signal that we have work to do AWC.PB508
|
||
DrawDesktop Move.L A3,-(SP) ; save a register AWC.PB508
|
||
Clr.L -(SP) ; function result AWC.PB508
|
||
_NewRgn ; get another new region AWC.PB508
|
||
Move.L (SP),A3 ; save it where we can keep an eye on it AWC.PB508
|
||
Move.L A3,D0 ; check for nil handle AWC.PB508
|
||
Beq.S NoRgn ; couldn't get one, so quit AWC.PB508
|
||
Move.L A2,-(SP) ; push pointer to device rect AWC.PB508
|
||
_RectRgn ; make a rectangular region out of it AWC.PB508
|
||
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB508
|
||
Move.L A3,-(SP) ; push temp region AWC.PB508
|
||
Move.L DeskRgn(A6),-(SP) ; put result back in DeskRgn AWC.PB508
|
||
_UnionRgn ; UnionRgn(DeskRgn,tempRgn,deskRgn) AWC.PB508
|
||
Move.L A3,-(SP) ; push temp region AWC.PB508
|
||
_DisposRgn ; dump it AWC.PB508
|
||
NoRgn Move.L (SP)+,A3 ; restore a register AWC.PB508
|
||
NoColorDesk Rts ; and go home AWC.PB508
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE SetDev; LOCAL;
|
||
;
|
||
; Renders or allocates myPalette as appropriate for the given device. If myPalette
|
||
; is polite it accumulates reference counts. If it is intolerant it assigns indexes
|
||
; according to closest match and makes these colors available in the color table. If
|
||
; it is adamant (animated) it chooses indexes according to lowest reference counts
|
||
; and reserves the entries on the device (setting the reserve bit).
|
||
;
|
||
; This function uses the stack frame built upon A6 and builds its own stack frame on A4.
|
||
|
||
SetDev PROC EXPORT
|
||
|
||
ResultRect equ -8 ; temp rect
|
||
OldPort equ ResultRect-4 ; a place to stuff the port while we InvalRect
|
||
SysUpdates equ OldPort-2 ; flag that tells whether the system wants updates
|
||
OldUpdates equ SysUpdates-2 ; flag => 1 if Old Quickdraw colors got changed AWC
|
||
VarSize equ OldUpdates ; number of bytes of variables AWC PB223
|
||
|
||
Link A4,#VarSize ; build stack frame
|
||
MoveM.L D3-D5/A2-A3,-(SP) ; save registers <AWC>
|
||
|
||
; Grab the device handle and shove it into theGDevice
|
||
|
||
Move CurDevice(A6),D3 ; get device offset
|
||
Move.L PDevPtr(A6),A0 ; get pointer to internal list of devices
|
||
Move.L (A0,D3.W*8),A0 ; get the device handle
|
||
Move.L A0,theGDevice ; set theGDevice
|
||
|
||
; Removed code that calculated device info - see CalcDevs below AWC PB223
|
||
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap
|
||
Move.L (A0),A0 ; dereference pixmap
|
||
Move.L pmTable(A0),A0 ; get handle to CTab
|
||
Move.L A0,DevCTab(A6) ; save color table handle, too
|
||
Move.L (A0),A0 ; dereference CTab
|
||
Move ctSize(A0),D0 ; grab number of entries - 1
|
||
Move D0,BlackIndex(A6) ; save it
|
||
AddQ #1,D0 ; bump it to number of entries
|
||
Move D0,DevIndexes(A6) ; save the number of indexes, too
|
||
|
||
; Compare the palette's seed for this device to the ctSeed belonging to the
|
||
; device. If they match, no environment or palette change has occurred. The routines
|
||
; which modify palettes make sure that the appropriate seed fields get changed. If
|
||
; the user modifies the palette herself, she must take responsibility for changing
|
||
; the seeds accordingly.
|
||
|
||
Move.L ctSeed(A0),D0 ; read the current device seed
|
||
Move.L PalettePtr(A6),A0 ; get the Palette pointer
|
||
BTst #DirtyBit,pmPrivate(A0) ; does it need an update anyway?
|
||
Bne.S DirtyBird ; yes => activate it anyway
|
||
|
||
Move.L pmSeeds(A0),A0 ; get the handle to the seeds
|
||
Move.L (A0),A0 ; dereference it
|
||
Cmp.L (A0,D3.W*4),D0 ; does the Palette's seed match the device's?
|
||
Beq GoHome ; yes => skip this whole mess
|
||
|
||
; Set up some useful pointers
|
||
|
||
DirtyBird Move.L PDevPtr(A6),A0 ; get pointer to internal list of devices
|
||
Lea (A0,D3.W*8),A0 ; point A0 at the device entry
|
||
Move.L A0,DevEntry(A6) ; save a pointer to the current device's entry
|
||
Move.L PMgrPtr(A6),A0 ; copy base pointer
|
||
AddA.L #LinkTabs,A0 ; add offset to first link table
|
||
Move D3,D0 ; get the device number (0..31)
|
||
Lsl #8,D0 ; multiply by link table size (max 31*1024)
|
||
Lea (A0,D0.W*4),A0 ; point A0 at link table
|
||
Move.L A0,DevLinks(A6) ; save pointer to device links table
|
||
|
||
; Set Updates to 0 so we'll know if a SetEntries is necessary. Make a copy
|
||
; of ciUsage flags in ciFlags.
|
||
|
||
Clr Updates(A6) ; clear number of updates to CTab we've done
|
||
Move myEntries(A6),D0 ; get myPalette^^.pmEntries
|
||
Move.L PalettePtr(A6),A0 ; get the pointer to the palette
|
||
Lea pmInfo(A0),A0 ; bump it to the first ColorInfo
|
||
Bra.S InitEnd ; jump into the fray
|
||
|
||
InitLoop Move ciUsage(A0),ciFlags(A0) ; copy ciUsage to ciFlags
|
||
AddA.L #ciSize,A0 ; bump A0 to the next ColorInfo
|
||
InitEnd DBra D0,InitLoop ; loop for pmEntries
|
||
|
||
Move.L PalettePtr(A6),A0 ; get the palette
|
||
Move pmPrivate(A0),D3 ; get the number of this palette
|
||
And #PIdMask,D3 ; clear the flag bits
|
||
Move.L DevCTab(A6),A0 ; get device CTabHandle
|
||
Move.L (A0),A0 ; dereference it
|
||
AddA.L #ctTable,A0 ; bump A0 to the start of the table
|
||
Move.L DevLinks(A6),A1 ; get device links table
|
||
Move DevIndexes(A6),D0 ; get number of entries on this device
|
||
MoveQ #0,D4 ; clear number that belong to us
|
||
MoveQ #0,D5 ; clear number available for pillaging
|
||
Move.L PMgrPtr(A6),A2 ; get the base pointer into A2
|
||
AddA.L #LinkTabs,A2 ; bump A2 to the start of the link tabs
|
||
Bra.S CountEnd ; jump into loop
|
||
|
||
CountLoop Move ForeLink(A1,D0.W*4),D1 ; fetch the link info for this entry, theGDevice
|
||
Beq.S ClearIt ; if 0, we didn't reserve it AWC.PB377
|
||
Bpl.S EndOfLink ; if >0 then we've found the end
|
||
NextIndex BfExtU D1{24:8},D2 ; get the index number (0..255)
|
||
BfExtU D1{19:5},D1 ; grab device number (0..31)
|
||
Lsl #8,D1 ; multiply by table size/4
|
||
Add D2,D1 ; add index to table offset
|
||
Move ForeLink(A2,D1.W*4),D1 ; get the next index; is it an endlink?
|
||
Bmi.S NextIndex ; no => find the next link
|
||
EndOfLink And #PIdMask,D1 ; clear all but the important bits
|
||
Cmp D3,D1 ; is this ours?
|
||
Bne.S NotThisOne ; no => bump Pillages
|
||
AddQ #1,D4 ; bump number we still have
|
||
Move #$4000,value(A0,D0.W*8) ; devctab => no protect, reserve, nopillage, our id
|
||
Bra.S CountEnd ; share code to force the device table
|
||
|
||
NotThisOne AddQ #1,D5 ; bump number we can pillage
|
||
FixCTab Move #$6000,value(A0,D0.W*8) ; devctab => no protect, reserve, pillage, our id
|
||
Bra.S CountEnd ; continue
|
||
|
||
ClearIt Clr value(A0,D0.W*8) ; device ctab => unused
|
||
CountEnd DBra D0,CountLoop ; continue for DevIndexes device entries
|
||
Move D5,Pillages(A6) ; remember how many we can pillage
|
||
Cmp Animators(A6),D4 ; have we all we want already?
|
||
Bpl.S QuickHandle ; yes => mark them handled <AWC>
|
||
Jsr Allocate ; yes => call allocation routine
|
||
Bra.S CheckTolrnt ; do the tolerant entries <AWC>
|
||
|
||
QuickHandle Move myEntries(A6),D0 ; get the number of entries <AWC>
|
||
Move.L PalettePtr(A6),A0 ; get palette pointer <AWC>
|
||
Lea pmInfo(A0),A0 ; bump A0 to the first ColorInfo <AWC>
|
||
Bra.S QuickEnd ; jump into loop <AWC>
|
||
|
||
QuickLoop Tst ciFlags(A0) ; is it handled? <AWC>
|
||
Bmi.S NextQuick ; yes => continue <AWC>
|
||
BTst #AnimatedBit,ciFlags+1(A0) ; is it animating? <AWC>
|
||
Beq.S NextQuick ; no => leave it alone <AWC>
|
||
BSet #HandledBit,ciFlags(A0) ; mark it handled <AWC>
|
||
NextQuick AddA.L #ciSize,A0 ; bump A0 to the next ColorInfo <AWC>
|
||
QuickEnd DBra D0,QuickLoop ; continue for pmEntries <AWC>
|
||
|
||
CheckTolrnt Tst Tolerators(A6) ; are there any tolerant entries?
|
||
Beq.S CheckUpdate ; no => tidy up
|
||
Move DevIndexes(A6),D0 ; get maximum number of entries
|
||
SubQ #2,D0 ; subtract black and white
|
||
Sub Animators(A6),D0 ; subtract our animators
|
||
Sub Pillages(A6),D0 ; subtract other reserved entries
|
||
Move D0,Regulators(A6) ; this is the number of regular entries left
|
||
Jsr Correlate ; yes => resolve collisions
|
||
|
||
; Now we are ready to set some colors (for real, man!). We have been changing colors
|
||
; in the device's color table all along. Now we just need to promulgate them through
|
||
; to the device with a sequential SetEntries call, but only if Updates is greater than
|
||
; zero. In order to make the call we have to unprotect each color and set it's client
|
||
; id to "none". Then we do the SetEntries call, after which we restore the protection
|
||
; and client id (255) of all colors. Next we copy the seed from the device color table
|
||
; to the palette so we'll know we've been here. Finally we generate update events for
|
||
; all windows of palettes which have been rendered on this device, including of course
|
||
; the current palette.
|
||
|
||
CheckUpdate Tst Updates(A6) ; have we changed anything?
|
||
Beq.S NoUpdate ; no => ignore this stuff
|
||
|
||
; Perform a sequential SetEntries call using the device's own color table.
|
||
|
||
Move.L theGDevice,A0 ; get the device
|
||
Move.L (A0),A0 ; dereference it
|
||
Clr gdId(A0) ; no client id's, please
|
||
|
||
Clr -(SP) ; push starting count of 0 for SetEntries
|
||
Move BlackIndex(A6),-(SP) ; push number of entries-1
|
||
Move.L DevCTab(A6),A0 ; get color table
|
||
Move.L (A0),A0 ; dereference it
|
||
Pea ctTable(A0) ; push address of the first ColorSpec
|
||
_SetEntries ; do it
|
||
|
||
NoUpdate Move.L DevCTab(A6),A0 ; get color table
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L ctSeed(A0),D0 ; read the current device seed
|
||
Move.L PalettePtr(A6),A0 ; get the Palette pointer
|
||
Move.L pmSeeds(A0),A1 ; get the handle to the seeds
|
||
Move.L (A1),A1 ; dereference it
|
||
Move CurDevice(A6),D3 ; get device number back
|
||
Move.L D0,(A1,D3.W*4) ; update the Palette's seed
|
||
|
||
; If we did not do the SetEntries, skip this part, too.
|
||
|
||
Tst Updates(A6) ; did we do a SetEntries?
|
||
Beq GoHome ; no => jump over the update code
|
||
|
||
; Here is where we add the portion of the port that touches this device to
|
||
; the palette's window's update region.
|
||
|
||
Pea OldPort(A4) ; where to put current GrafPtr
|
||
_GetPort ; get it
|
||
|
||
Move.L theGDevice,A0 ; get theGDevice
|
||
Move.L (A0),A0 ; dereference it
|
||
Lea gdRect(A0),A2 ; get address of device rect into A2
|
||
Move gdFlags(A0),D0 ; get flags
|
||
BTst #mainScreen,D0 ; is it the main screen?
|
||
Beq.S NoMenuFix ; no => don't update the menu
|
||
Move.L MenuList,D0 ; get the MenuList handle; is it nil? AWC.PB508
|
||
Beq.S NoMenuFix ; yes => don't redraw the menu bar AWC.PB508
|
||
Move.L D0,A0 ; get ready to dereference it AWC.PB508
|
||
Tst.L (A0) ; has it been purged? AWC.PB508
|
||
Beq.S NoMenuFix ; yes => don't redraw the menu bar AWC.PB508
|
||
_DrawMenuBar ; redraw the menu bar AWC.PB508
|
||
NoMenuFix MoveQ #0,D0 ; we want no updates if no SysPalette AWC PB223
|
||
Move.L AppPalette,A0 ; fetch the application's palette, if any AWC.PB457
|
||
Move.L A0,D1 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
|
||
Bne.S UseAppPltt ; no => use the application's palette AWC.PB457
|
||
Move.L PMgrPtr(A6),A0 ; fetch our data pointer
|
||
Move.L SysPalette(A0),A0 ; fetch the system palette
|
||
Move.L A0,D1 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
|
||
Beq.S NoSysP ; yes => we update
|
||
UseAppPltt Move.L (A0),A0 ; dereference AppPalette or SysPalette AWC.PB457
|
||
Move pmPrivate(A0),D0 ; get update information AWC PB224
|
||
And #$C000,D0 ; and it with the proper flags AWC PB224
|
||
NoSysP Move D0,SysUpdates(A4) ; set update information AWC PB224
|
||
Move #JugglerTrap,D0 ; #$A88F AWC PB224
|
||
_GetTrapAddress ; find out what the trap is AWC PB224
|
||
Move.L A0,-(SP) ; save it AWC PB224
|
||
Move #UnimplementedTrap,D0 ; #$A89F AWC PB224
|
||
_GetTrapAddress ; where do unimplemented traps go AWC PB224
|
||
CmpA.L (SP)+,A0 ; are we Jugglerªing? AWC PB224
|
||
Beq.S NotJuggling ; no => handle updates the old way AWC PB224
|
||
Move.L A2,-(SP) ; push device rect on the stack AWC PB224
|
||
Move CurDevice(A6),-(SP) ; push PaletteMgr device number AWC PB224
|
||
Move SysUpdates(A4),-(SP) ; push default updates for old ports AWC PB224
|
||
Move #ColorInvalRect,-(SP) ; push the selector for _ColorInvalRect AWC PB224
|
||
_Juggler ; call Erich's disgusting C code AWC PB224
|
||
bra EndJuggling ; skip over the regular update code AWC PB224
|
||
|
||
NotJuggling Move.L WindowList,A3 ; get start of window list AWC PB224
|
||
WindowLoop Move SysUpdates(A4),D1 ; reset the default update value AWC.PB480
|
||
Move #CBackBit,D0 ; grab a constant AWC PB224
|
||
CmpA.L WindowCopy(A6),A3 ; is it us?
|
||
Bne.S NotCurrent ; no => check for background updates
|
||
Move #CForeBit,D0 ; grab a different constant AWC PB223
|
||
NotCurrent Tst.B wVisible(A3) ; is this window visible?
|
||
Beq.S NextWind ; no => do the next window <C864>
|
||
Tst PortBits+RowBytes(A3) ; is it a color window?
|
||
Bpl.S UseDefault ; no => handle an old style window AWC.PB480
|
||
Move.L GrafVars(A3),A0 ; get the extended variables handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L PmFgColor(A0),A0 ; get the window's palette, if any
|
||
CmpA.L #Nil,A0 ; is it nil?
|
||
Beq.S UseDefault ; yes => default to the system value AWC.PB480
|
||
Move.L (A0),A0 ; dereference the palette
|
||
Move pmPrivate(A0),D1 ; fetch the palette's update values AWC.PB480
|
||
UseDefault BTst D0,D1 ; does the caller want this update? AWC.PB480
|
||
Beq.S NextWind ; no => do the next window
|
||
|
||
; We now must check to see if the window we're examining intersects the device
|
||
; we're working upon. We'll GlobalToLocal the device rect and simultaneously
|
||
; intersect it with the window's portRect. If we detect an intersection then
|
||
; we'll have calculated the rectangle we'll need for the InvalRect. First we
|
||
; point A0 at the Bounds rect for the port so we can put DevRect in local space.
|
||
|
||
Lea PortBits(A3),A0 ; point A0 at potential bitmap AWC.PB480
|
||
Tst RowBytes(A0) ; bitmap or pixmap? AWC.PB480
|
||
Bpl.S GotBitmap ; no high bit in Rowbytes => bitmap AWC.PB480
|
||
Move.L BaseAddr(A0),A0 ; get Port's Pixmap handle AWC.PB480
|
||
Move.L (A0),A0 ; get Pixmap pointer AWC.PB480
|
||
GotBitmap Lea Bounds(A0),A0 ; advance A0 to Bounds rect AWC.PB480
|
||
Move Top(A2),D0 ; get device top AWC.PB480
|
||
Add Top(A0),D0 ; subtract bounds top AWC.PB480
|
||
Cmp PortRect+Bottom(A3),D0 ; is Dest.Top >= Port.Bottom? AWC.PB480
|
||
Bge.S NextWind ; yes => no intersection AWC.PB480
|
||
Move D0,ResultRect+Top(A4) ; save it AWC.PB480
|
||
Move Left(A2),D0 ; get device left AWC.PB480
|
||
Add Left(A0),D0 ; subtract bounds left AWC.PB480
|
||
Cmp PortRect+Right(A3),D0 ; is Dest.Left >= Port.Right? AWC.PB480
|
||
Bge.S NextWind ; yes => no intersection AWC.PB480
|
||
Move D0,ResultRect+Left(A4) ; save left AWC.PB480
|
||
Move Bottom(A2),D0 ; get bottom AWC.PB480
|
||
Add Top(A0),D0 ; subtract bounds top AWC.PB480
|
||
Cmp PortRect+Top(A3),D0 ; is Dest.Bottom <= Port.Top? AWC.PB480
|
||
Ble.S NextWind ; yes => no intersection AWC.PB480
|
||
Move D0,ResultRect+Bottom(A4) ; save bottom AWC.PB480
|
||
Move Right(A2),D0 ; get right AWC.PB480
|
||
Add Left(A0),D0 ; subtract bounds left AWC.PB480
|
||
Cmp PortRect+Left(A3),D0 ; is Dest.Right <= Port.Left? AWC.PB480
|
||
Ble.S NextWind ; yes => no intersection AWC.PB480
|
||
Move D0,ResultRect+Right(A4) ; save right AWC.PB480
|
||
Move.L A3,-(SP) ; push this window's pointer AWC.PB480
|
||
_SetPort ; make it the current port AWC.PB480
|
||
Pea ResultRect(A4) ; move device rect (local) onto the stack AWC.PB480
|
||
_InvalRect ; invalidate it AWC.PB480
|
||
|
||
NextWind Move.L NextWindow(A3),A3 ; grab the next window in the list
|
||
CmpA.L #Nil,A3 ; is it nil?
|
||
Bne WindowLoop ; no => continue
|
||
Bsr RedrawDesktop ; redraw the desktop AWC.PB508
|
||
EndJuggling Move.L OldPort(A4),-(SP) ; push old port
|
||
_SetPort ; restore old port
|
||
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
|
||
MoveM.L (SP)+,D3-D5/A2-A3 ; restore registers <AWC>
|
||
Unlk A4 ; clear stack frame
|
||
Rts ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE CalcDevs; LOCAL;
|
||
;
|
||
|
||
CalcDevs PROC EXPORT
|
||
|
||
ResultRect equ -8 ; temp rect AWC PB223
|
||
SpotLight equ ResultRect-2 ; boolean for WindowCopy = FrontWindow AWC PB223
|
||
VarSize equ SpotLight ; bytes of variables AWC PB223
|
||
|
||
Link A4,#VarSize ; build stack frame AWC PB223
|
||
MoveM.L D3-D5/A2-A3,-(SP) ; save registers AWC PB223
|
||
MoveQ #0,D3 ; clear device set AWC PB223
|
||
MoveQ #0,D4 ; clear front set AWC PB223
|
||
|
||
; Point A0 at the Bounds rect of WindowCopy
|
||
|
||
Move.L WindowCopy(A6),A3 ; get window pointer AWC PB223
|
||
Lea PortBits(A3),A0 ; point A0 at potential bitmap AWC PB223
|
||
Tst RowBytes(A0) ; is it a color window? AWC PB223
|
||
Bpl.S OldPort ; no => it's an old port AWC PB223
|
||
Move.L BaseAddr(A0),A0 ; get Port's Pixmap handle AWC PB223
|
||
Move.L (A0),A0 ; get Pixmap pointer AWC PB223
|
||
OldPort Move.L ScrnBase,D0 ; get main screen AWC PB223
|
||
Cmp.L BaseAddr(A0),D0 ; do we point at the main screen? AWC PB223
|
||
Bne GoHome ; no => it doesn't count; go home AWC PB223
|
||
Lea Bounds(A0),A0 ; advance A0 to Bounds rect AWC PB223
|
||
Lea PortRect(A3),A1 ; advance A1 to Port rect AWC PB223
|
||
|
||
; Calculate PortRect in global coordinates
|
||
|
||
Move Top(A1),D0 ; get port top AWC PB223
|
||
Sub Top(A0),D0 ; subtract bounds top AWC PB223
|
||
Move D0,WindowRect+Top(A6) ; save it AWC PB223
|
||
Move Left(A1),D0 ; get port left AWC PB223
|
||
Sub Left(A0),D0 ; subtract bounds left AWC PB223
|
||
Move D0,WindowRect+Left(A6) ; save left AWC PB223
|
||
Move Bottom(A1),D0 ; get port bottom AWC PB223
|
||
Sub Top(A0),D0 ; subtract bounds top AWC PB223
|
||
Move D0,WindowRect+Bottom(A6) ; save bottom AWC PB223
|
||
Move Right(A1),D0 ; get port right AWC PB223
|
||
Sub Left(A0),D0 ; subtract bounds left AWC PB223
|
||
Move D0,WindowRect+Right(A6) ; save right AWC PB223
|
||
|
||
; Determine whether or not this is the FrontWindow
|
||
|
||
Clr SpotLight(A4) ; SpotLight := false AWC.PB485
|
||
Clr.L -(SP) ; function result AWC.PB223
|
||
_FrontWindow ; get the current front window AWC.PB223
|
||
CmpA.L (SP)+,A3 ; is this FrontWindow? AWC.PB223
|
||
Bne.S NotSpotted ; no => continue AWC.PB485
|
||
Move.B wHilited(A3),SpotLight(A4) ; FrontWindow if highlighted AWC.PB485
|
||
|
||
NotSpotted Move.L PMgrHandle,A2 ; get PMgrHandle AWC PB223
|
||
Move.L (A2),A2 ; dereference it AWC PB223
|
||
MoveQ #0,D3 ; clear Devices in D3 AWC PB223
|
||
Move nDevs(A2),D5 ; keep device number in D5 AWC PB223
|
||
Lea DevHandles(A2),A2 ; point to the first PMgr device AWC PB223
|
||
Bra.S DeviceEnd ; jump into calc loop AWC PB223
|
||
|
||
DeviceLoop Move.L (A2,D5.W*8),A0 ; copy device handle AWC PB223
|
||
Move.L (A0),A0 ; dereference it AWC PB223
|
||
Clr -(SP) ; boolean result of SectRect AWC PB223
|
||
Pea WindowRect(A6) ; port rect in global coordinates AWC PB223
|
||
Pea gdRect(A0) ; device rect AWC PB223
|
||
Pea ResultRect(A4) ; where to shove result AWC PB223
|
||
_SectRect ; calculate intersection AWC PB223
|
||
Move (SP)+,D0 ; do they intersect? AWC PB223
|
||
Beq.S DeviceEnd ; no => don't set device bit AWC PB223
|
||
BSet D5,D3 ; set device bit in D3 AWC PB223
|
||
Move.L PDevPtr(A6),A0 ; get pointer to CLUT device list AWC PB223
|
||
Tst.B SpotLight(A4) ; is this the FrontWindow? AWC PB223
|
||
Beq.S CheckPrior ; no => see if it is FrontMost instead AWC PB223
|
||
Move.L A3,DevFrontMost(A0,D5*8); save it as the new FrontMost AWC PB223
|
||
Bra.S SetFront ; and skip ahead AWC PB223
|
||
|
||
CheckPrior CmpA.L DevFrontMost(A0,D5*8),A3; is this window frontmost on this device? AWC PB223
|
||
Bne.S DeviceEnd ; no => don't set frontmost bit AWC PB223
|
||
SetFront BSet D5,D4 ; set frontmost bit in D4 AWC PB223
|
||
DeviceEnd DBra D5,DeviceLoop ; check next device AWC PB223
|
||
|
||
GoHome Move.L D3,DeviceSet(A6) ; save device set AWC PB223
|
||
Move.L D4,FrontSet(A6) ; save frontmost set AWC PB223
|
||
MoveM.L (SP)+,D3-D5/A2-A3 ; restore registers AWC PB223
|
||
Unlk A4 ; clear stack frame AWC PB223
|
||
Rts ; strip parameters and go home AWC PB223
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE ActivatePalette(dstWindow: WindowPtr); INLINE $AA94;
|
||
;
|
||
|
||
ActivatePalette PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
dstWindow equ ParamSize+8-4 ; source Palette handle
|
||
|
||
; The ActivatePalette stack frame is defined at the global level so it can be accessed
|
||
; by each of the routines subsidiary to ActivatePalette and thereby avoid gross parameter
|
||
; passing. All such subsidiary routines will link with A4 and not A6 thus keeping
|
||
; ActivatePalette's stack frame intact. D3 is used to hold any error condition.
|
||
; It is moved to D0 before we quit.
|
||
|
||
Link A6,#spVarSize ; build stack frame
|
||
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
|
||
|
||
MoveQ #1,D3 ; set error flag in case we branch
|
||
Move.L PMgrHandle,A2 ; get global handle
|
||
CmpA.L #PMgrNil,A2 ; is it nil?
|
||
Beq GoHome ; it has to be initialized
|
||
|
||
Move.L (A2),A0 ; dereference PMgrHandle AWC.PB500
|
||
Move nDevs(A0),D0 ; are there any clut devices? AWC.PB500
|
||
Beq GoHome ; no => punt AWC.PB500
|
||
|
||
Move.L dstWindow(A6),A3 ; get the window pointer
|
||
CmpA.L #Nil,A3 ; is it real?
|
||
Beq GoHome ; no => go home <AWC/PB150>
|
||
Move.L A3,WindowCopy(A6) ; save a copy for those who need it
|
||
|
||
Tst PortBits+RowBytes(A3) ; is it a new port?
|
||
Bpl.S TrySystem ; no => try for a system palette
|
||
Move.L GrafVars(A3),A0 ; get the GrafVars handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L PmFgColor(A0),A3 ; save the palette handle in GrafVars
|
||
CmpA.L #Nil,A3 ; is it nil?
|
||
Bne.S FoundPltt ; no => we've found it
|
||
TrySystem Move.L AppPalette,A3 ; get the layer's palette, if any AWC.PB457
|
||
Move.L A3,D0 ; CmpA.L #Nil,A0; is AppPalette nil? AWC.PB457
|
||
Bne.S FoundPltt ; no => use AppPalette AWC.PB457
|
||
Move.L (A2),A0 ; dereference PMgrHandle
|
||
Move.L SysPalette(A0),A3 ; get the system palette, if any
|
||
Move.L A3,D0 ; CmpA.L #Nil,A3; is SysPalette nil? AWC.PB457
|
||
Beq GoHome ; yes => we can't do it
|
||
FoundPltt Move.L A3,PaletteH(A6) ; save the palette for later
|
||
|
||
; past this point we will have locked PMgrHandle and PaletteH. We also save theGDevice
|
||
; and clear the InfoHandle variable.
|
||
|
||
Move.L A2,A0 ; copy PMgrHandle
|
||
_HLock ; lock it down
|
||
Move.L A3,A0 ; copy PaletteH
|
||
_HLock ; lock it down as well
|
||
Move.L (A2),A4 ; dereference PMgrHandle
|
||
Move.L A4,PMgrPtr(A6) ; save a copy of the pointer
|
||
Move.L PListHandle(A4),A0 ; get PListHandle
|
||
_HLock ; lock it down
|
||
Move.L (A0),PListPtr(A6) ; save pointer to palette list
|
||
Move nDevs(A4),Devices(A6) ; save number of devices in our list
|
||
Lea DevHandles(A4),A0 ; point A4 at first device handle
|
||
Move.L A0,PDevPtr(A6) ; save pointer to start of device list
|
||
Move.L theGDevice,SaveGDev(A6) ; save theGDevice handle
|
||
Clr.L InfoHandle(A6) ; mark it as unallocated
|
||
Move.L (A3),A4 ; dereference PaletteH
|
||
Move.L A4,PalettePtr(A6) ; save it for posterior
|
||
Move pmEntries(A4),D4 ; fetch number of entries
|
||
Move D4,myEntries(A6) ; save it for posterity
|
||
Clr MAnimators(A6) ; MAnimators := 0
|
||
Clr MTolerators(A6) ; MTolerators := 0
|
||
|
||
; Check to see on which devices the window is now rendered
|
||
|
||
Jsr CalcDevs ; determine the new and frontmost device sets
|
||
Tst.L FrontSet(A6) ; is this window frontmost on any device?
|
||
Beq NoFunStuff ; no => skip our wonderful rendering code
|
||
|
||
; Count the number of animating and tolerant colors. Mark explicit, dithered, and
|
||
; courteous colors as "handled" so we won't bother with them in SetDev et al.
|
||
|
||
Lea pmInfo(A4),A4 ; point us at the first ColorInfo
|
||
Bra.S ExamEnd ; jump into DBra loop
|
||
|
||
ExamLoop Move ciUsage(A4),D1 ; copy ciUsage field of current entry
|
||
Cmp #pmDithered,D1 ; is it pmDithered or pmCourteous?
|
||
Ble.S HandleColor ; pmCourteous => mark as handled
|
||
BTst #ExplicitBit,D1 ; pmExplicit?
|
||
Bne.S HandleColor ; yes => mark it as handled, too
|
||
BTst #AnimatedBit,D1 ; pmAnimated?
|
||
Beq.S CheckTolrnt ; no => check for other kinds of usage
|
||
AddQ #1,MAnimators(A6) ; bump number of animating colors
|
||
Bra.S NextColor ; continue
|
||
|
||
; Any color which can match black or white within tolerance is removed from consideration.
|
||
; We guarantee that black and white will be around, so as long as you don't have to change
|
||
; their values you can match them normally. When we correlate colors we won't allow you
|
||
; to match black or white because we'll know you would have to change them.
|
||
|
||
CheckTolrnt AddQ #1,MTolerators(A6) ; yes => bump number of tolerant colors
|
||
Bra.S NextColor ; continue
|
||
|
||
HandleColor BSet #HandledBit,ciUsage(A4) ; mark explicit and normal colors as handled
|
||
NextColor Add #ciSize,A4 ; bump address to next ColorInfo
|
||
ExamEnd DBra D4,ExamLoop ; loop for all pmEntries
|
||
|
||
; See if we have any animating or tolerant entries. If not, we can skip most of this
|
||
|
||
Move MAnimators(A6),D0 ; do we have any animating AWC PB223
|
||
Or MTolerators(A6),D0 ; or tolerant entries? AWC PB223
|
||
Beq NoFunStuff ; no => just clean up the world AWC.PB508
|
||
|
||
; Allocate a scratch buffer
|
||
|
||
Move.L #InfoHandSz,D0 ; size of our scratch area AWC
|
||
_NewHandle ,CLEAR ; allocate a scratch area
|
||
Bne UnlockEm ; we couldn't get it - D3 still says "error" AWC.PB508
|
||
Move.L A0,InfoHandle(A6) ; save it
|
||
_HLock ; lock it
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L A0,InfoPtr(A6) ; save dereferenced ptr
|
||
|
||
; Call SetDev to render or record the Palette on each device, as appropriate.
|
||
|
||
; Clr.L DeviceSet(A6) ; zero bitmap of devices
|
||
MoveQ #0,D4 ; clear device counter
|
||
Clr GrayRgnPrep(A6) ; GrayRgnPrep := false AWC.PB508
|
||
DeviceLoop Move.L FrontSet(A6),D0 ; grab the front device set AWC PB223
|
||
BTst D4,D0 ; frontmost on this clut device? AWC PB223
|
||
Beq.S NoDevError ; no => jump across SetDev AWC PB223
|
||
Move MAnimators(A6),Animators(A6) ; copy MAnimators
|
||
Move MTolerators(A6),Tolerators(A6) ; copy MTolerators
|
||
Move D4,CurDevice(A6) ; copy it for SetDev
|
||
Jsr SetDev ; render palette; did we get an error?
|
||
Beq.S NoDevError ; did we find an error?
|
||
AddQ #1,D3 ; bump our error count
|
||
NoDevError AddQ #1,D4 ; we've examined another device
|
||
Cmp Devices(A6),D4 ; have we done them all
|
||
Bmi.S DeviceLoop ; no => do another
|
||
|
||
Move.L SaveGDev(A6),theGDevice ; restore theGDevice handle AWC.PB508
|
||
Move GrayRgnPrep(A6),D0 ; see how we faired on the desktop AWC.PB508
|
||
Beq.S NoFunStuff ; no => nothing to do AWC.PB508
|
||
Cmp #-1,D0 ; did we detect no work to do? AWC.PB508
|
||
Beq.S NoFunStuff ; yes => nothing to do AWC.PB508
|
||
SubQ.L #4,SP ; open room for the old port AWC.PB520
|
||
Pea (SP) ; push a pointer to that location AWC.PB520
|
||
_GetPort ; save the old port AWC.PB520
|
||
Move.L WMgrCPort,-(SP) ; gpush WMgrPort for SetPort AWC.PB520
|
||
_SetPort ; do it AWC.PB520
|
||
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB520
|
||
_SetClip ; clip to DeskRgn AWC.PB520
|
||
Clr.L -(SP) ; push nil AWC.PB520
|
||
_ClipAbove ; set GrayRgn AWC.PB520
|
||
Move.L DeskHook,D0 ; is there a DeskHook? AWC.PB520
|
||
Bne.S CallHook ; yes => call the deskhook AWC.PB508
|
||
Clr.L -(SP) ; push nil AWC.PB508
|
||
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB508
|
||
_PaintOne ; update the desktop AWC.PB508
|
||
Bra.S RestorePort ; catch up with the latest news AWC.PB520
|
||
|
||
CallHook Move.L D0,A0 ; put DeskHook address into A0 AWC.PB508
|
||
MoveQ #0,D0 ; pass a paint message in D0 AWC.PB508
|
||
Jsr (A0) ; let the Hook do the painting AWC.PB508
|
||
RestorePort _SetPort ; pop the old port AWC.PB520
|
||
Move.L DeskRgn(A6),-(SP) ; push DeskRgn AWC.PB508
|
||
_DisposRgn ; get rid of it AWC.PB508
|
||
NoFunStuff Move.L PMgrPtr(A6),A0 ; get the PMgrHandle pointer AWC PB223
|
||
Move.L PListHandle(A0),A0 ; get the PListHandle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L PalettePtr(A6),A1 ; get the Palette
|
||
Move pmPrivate(A1),D0 ; get the entry number
|
||
And #PIdMask,D0 ; clear the flag bits
|
||
Move Reserves(A0,D0.W*8),D0 ; does this palette have anything reserved?
|
||
Beq.S NoneRsrvd ; no => forget about clearing AWC PB223
|
||
|
||
; Clear any unused devices and update device bitmap
|
||
|
||
Move.L PalettePtr(A6),A0 ; get palette pointer
|
||
Move.L pmDevices(A0),D0 ; get former device set
|
||
Move.L DeviceSet(A6),D1 ; get new device set
|
||
Not.L D1 ; complement the current set
|
||
And.L D1,D0 ; remove any current bits
|
||
Beq.S NoneRsrvd ; if none needing unreserving, quit
|
||
|
||
; STAGE 1 - implement
|
||
;
|
||
; Loop, clearing each device we once did but no longer touch. This is a good thing to
|
||
; add in the future. For now, it won't have a lot of impact. The entries it still has
|
||
; reserved can always be pillaged by somebody else if they need them. But, in the next
|
||
; version we shall release entries as we move off a device.
|
||
|
||
Nop
|
||
|
||
NoneRsrvd Move.L DeviceSet(A6),pmDevices(A1) ; copy the new device set
|
||
SubQ #1,D3 ; if now 0 then we got through with no errors
|
||
UnlockEm Move.L PMgrPtr(A6),A0 ; get the master pointer
|
||
Move.L PListHandle(A0),A0 ; get this handle
|
||
_HUnlock ; unlock it
|
||
Move.L A2,A0 ; copy PMgrHandle
|
||
_HUnLock
|
||
|
||
; clear the dirty bit and restore the user's ciUsage fields
|
||
|
||
Move.L PalettePtr(A6),A0 ; get Palette pointer
|
||
BClr #DirtyBit,pmPrivate(A0) ; clear the dirty bit
|
||
Move pmEntries(A0),D0 ; fetch number of entries
|
||
Lea pmInfo(A0),A0 ; point us at the first ColorInfo
|
||
Bra.S UnsetEnd ; jump into DBra loop
|
||
|
||
UnsetLoop Move ciUsage(A0),D1 ; copy ciUsage field of current entry
|
||
And #ClearBits,D1 ; clear all but the user's flags
|
||
Move D1,ciUsage(A0) ; restore it
|
||
AddA.L #ciSize,A0 ; bump A4 to the next color info
|
||
UnsetEnd DBra D0,UnsetLoop ; loop for all pmEntries ColorInfo's
|
||
|
||
Move.L A3,A0 ; copy PaletteHandle to A0
|
||
_HUnlock ; unlock it
|
||
Move.L InfoHandle(A6),A0 ; get scratch handle
|
||
CmpA.L #Nil,A0 ; was it allocated
|
||
Beq.S NoError ; no => don't dispose it
|
||
_DisposHandle ; get rid of it
|
||
NoError MoveQ #0,D3 ; clear error flag
|
||
GoHome Move.L D3,D0 ; copy error flag
|
||
MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE DirtySeeds(dstPalette: PaletteHandle); LOCAL;
|
||
;
|
||
|
||
DirtySeeds PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
dstPalette equ ParamSize+8-4 ; destination Palette handle
|
||
|
||
VarSize equ 0 ; size of variables
|
||
|
||
Link A6,#VarSize ; build stack frame AWC.PB508
|
||
Move.L PMgrHandle,A0 ; get the PMgrHandle (we assume its safe) AWC.PB508
|
||
Move.L (A0),A0 ; dereference it AWC.PB508
|
||
Move SeedHSize(A0),D0 ; get the seed handle size AWC.PB508
|
||
Lsr #2,D0 ; divide it by 4 to get number of longs AWC.PB508
|
||
SubQ #1,D0 ; decrement it for the DBra loop AWC.PB508
|
||
Move.L DstPalette(A6),A0 ; get the palette AWC.PB508
|
||
Move.L (A0),A0 ; dereference it AWC.PB508
|
||
BSet #DirtyBit,pmPrivate(A0) ; set the dirty bit AWC.PB508
|
||
Move.L pmSeeds(A0),A0 ; get the seeds handle AWC.PB508
|
||
Move.L (A0),A0 ; dereference it AWC.PB508
|
||
ClearLoop Clr.L (A0)+ ; clear a seed AWC.PB508
|
||
DBra D0,ClearLoop ; continue AWC.PB508
|
||
GoHome Unlk A6 ; clear stack frame AWC.PB508
|
||
Rtd #ParamSize ; strip parameters and go home AWC.PB508
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE SetPalette(dstWindow: WindowPtr; srcPalette: PaletteHandle; CUpdates: BOOLEAN);
|
||
; INLINE $AA95;
|
||
;
|
||
|
||
SetPalette PROC EXPORT
|
||
|
||
ParamSize equ 10 ; total bytes of params
|
||
dstWindow equ ParamSize+8-4 ; source Palette handle
|
||
srcPalette equ dstWindow-4 ; new window, if any
|
||
CUpdates equ srcPalette-2 ; whether we want background color updates
|
||
|
||
VarSize equ 0 ; size of variables
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
|
||
Move.L PMgrHandle,A1 ; we have to be initialized
|
||
CmpA.L #PMgrNil,A1 ; is it initialized?
|
||
Beq GoHome ; no => punt
|
||
|
||
Move.L dstWindow(A6),A0 ; get the window pointer
|
||
CmpA.L #-1,A0 ; does the caller want to set AppPalette?
|
||
Bne.S NotSystem ; no => go look for the window
|
||
|
||
Move.L AppPalette,D0 ; get the application palette; is it nil? AWC.PB457
|
||
Beq.S NoAppPltt ; yes => don't dispose it AWC.PB457
|
||
Move.L D0,A0 ; put it in an address register AWC.PB457
|
||
Move.L (A0),A0 ; dereference it AWC.PB457
|
||
BTst #DisposeBit,pmPrivate(A0) ; should we clobber it? AWC.PB457
|
||
Beq.S NoAppPltt ; no => the caller deals with it AWC.PB457
|
||
Move.L D0,-(SP) ; push the palette AWC.PB457
|
||
_DisposePalette ; can you say "bye bye"? AWC.PB457
|
||
NoAppPltt Move.L SrcPalette(A6),A0 ; get the palette parameter AWC.PB457
|
||
Move.L A0,AppPalette ; set the layer palette; is it nil? AWC.PB457
|
||
Bne.S AppNotNil ; no => activate the layer palette AWC.PB457
|
||
Move.L (A1),A0 ; dereference PMgrHandle AWC.PB457
|
||
Move.L SysPalette(A0),A0 ; get the system palette AWC.PB457
|
||
Move.L A0,D0 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
|
||
Beq.S GoHome ; yes => shouldn't happen, but quit anyway AWC.PB457
|
||
AppNotNil Move.L A0,-(SP) ; push the palette pointer AWC.PB508
|
||
Bsr DirtySeeds ; clear the device seeds so we'll update AWC.PB508
|
||
Clr.L -(SP) ; push function result AWC.PB439
|
||
_FrontWindow ; push the front window AWC.PB439
|
||
Bra.S DontClear ; activate it AWC PB223
|
||
|
||
NotSystem Tst PortBits+RowBytes(A0) ; is it a new port?
|
||
Bpl.S GoHome ; if not, we're out of here
|
||
Move.L srcPalette(A6),D0 ; get the palette handle
|
||
|
||
Move.L GrafVars(A0),A1 ; get handle to GrafVars
|
||
Move.L (A1),A1 ; dereference GrafVars
|
||
Move.L PmFgColor(A1),D1 ; save whatever's there currently
|
||
Move.L D0,PmFgColor(A1) ; store the palette in GrafVars.PmFgColor; is it nil?
|
||
Beq.S BitsOkay ; yes => that's okay, but we won't dereference it
|
||
Move.L D0,A1 ; put the Palette handle into A1
|
||
Move.L (A1),A1 ; dereference it
|
||
; Move.L A0,pmWindow(A1) ; store the window in the palette AWC.PB439
|
||
|
||
BClr #CBackBit,PmPrivate(A1) ; clear background update bit AWC PB223
|
||
BSet #CForeBit,PmPrivate(A1) ; set foreground update bit AWC PB223
|
||
Tst.B CUpdates(A6) ; does she want background updates? AWC PB223
|
||
Beq.S BitsOkay ; 0 => default case, CUpdates = false AWC PB223
|
||
Bpl.S AllowBacks ; 1 => CUpdates = true AWC PB223
|
||
BTst #NForeBit,CUpdates(A6) ; does he want foreground updates? AWC PB223
|
||
Bne.S YesFores ; yes => leave it as is AWC PB223
|
||
BClr #CForeBit,PmPrivate(A1) ; turn foreground updates off AWC PB223
|
||
YesFores BTst #NBackBit,CUpdates(A6) ; does she want background updates? AWC PB223
|
||
Beq.S BitsOkay ; no => skip it AWC PB223
|
||
AllowBacks BSet #CBackBit,PmPrivate(A1) ; set the foreground update bit AWC PB223
|
||
BitsOkay Cmp.L D0,D1 ; are they identical? AWC PB223
|
||
Beq.S GoHome ; don't bother activating anything
|
||
Move.L A0,-(SP) ; push the window pointer for the activate palette
|
||
Tst.L D1 ; is this nil?
|
||
Beq.S DontClear ; don't clear it
|
||
Move.L D1,A0 ; copy it to an address register AWC.PB457
|
||
Move.L (A0),A0 ; dereference it AWC.PB457
|
||
BTst #DisposeBit,pmPrivate(A0) ; should we dispose it? AWC.PB457
|
||
Beq.S DontClear ; no => leave it alone AWC.PB457
|
||
Move.L D1,-(SP) ; push the old handle
|
||
_DisposePalette ; can you say "bye bye"? I knew you could AWC.PB457
|
||
DontClear _ActivatePalette ; set the palette if it happens to be FrontWIndow
|
||
GoHome Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; FUNCTION GetPalette(srcWindow: WindowPtr) : PaletteHandle; INLINE $AA96;
|
||
;
|
||
|
||
GetPalette PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
GetResult equ ParamSize+12-4 ; result palette handle
|
||
srcWindow equ GetResult-4 ; source window to help find the palette
|
||
|
||
VarSize equ 0 ; size of variables
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Clr.L GetResult(A6) ; clear the result handle
|
||
|
||
Move.L PMgrHandle,A1 ; we have to be initialized
|
||
CmpA.L #PMgrNil,A1 ; is it initialized?
|
||
Beq.S GoHome ; no => punt
|
||
|
||
Move.L srcWindow(A6),A0 ; get the window pointer
|
||
CmpA.L #Nil,A0 ; is it real?
|
||
Beq.S GoHome ; no => punt
|
||
CmpA.L #-1,A0 ; do they want the system palette?
|
||
Bne.S NotSystem ; no, not the system
|
||
Move.L AppPalette,GetResult(A6) ; grab AppPalette; is it nil? AWC.PB457
|
||
Bne.S GoHome ; no => we're done AWC.PB457
|
||
|
||
Move.L (A1),A1 ; dereference PMgrHandle AWC.PB457
|
||
Move.L SysPalette(A1),A0 ; get SysPalette AWC.PB457
|
||
Move.L A0,D0 ; CmpA.L #Nil,A0; is it nil? AWC.PB457
|
||
Beq.S GoHome ; yes => how did this happen? oh well, quit AWC.PB457
|
||
_HandToHand ; make a copy of it AWC.PB457
|
||
Tst D0 ; did the call succeed? AWC.PB457
|
||
Bne.S GoHome ; no => go home with result nil AWC.PB457
|
||
Move.L A0,AppPalette ; now we'll use the copy AWC.PB457
|
||
Move.L A0,GetResult(A6) ; give them the copy's handle AWC.PB457
|
||
Move.L A0,-(SP) ; push the handle for RecordPalette AWC.PB457
|
||
Move.L (A0),A0 ; dereference it AWC.PB457
|
||
Clr.L pmSeeds(A0) ; kill the copy of the seeds handle AWC.PB457
|
||
BClr #DisposeBit,pmPrivate(A0) ; caller must now dispose it AWC.PB457
|
||
Jsr RecordPalette ; insert it into our list of known things AWC.PB457
|
||
Beq.S GoHome ; scurry out of here AWC.PB457
|
||
Clr.L AppPalette ; sorry, it failed AWC.PB457
|
||
Clr.L GetResult(A6) ; so clear the result, too AWC.PB457
|
||
Bra.S GoHome ; continue AWC.PB457
|
||
|
||
NotSystem Tst PortBits+RowBytes(A0) ; is it a new port?
|
||
Bpl.S GoHome ; if not, we're out of here
|
||
Move.L GrafVars(A0),A0 ; get handle to GrafVars
|
||
Move.L (A0),A0 ; dereference GrafVars
|
||
Move.L PmFgColor(A0),A0 ; get the palette AWC.PB457
|
||
Move.L A0,GetResult(A6) ; give it to the caller; is it nil? AWC.PB457
|
||
Beq.S GoHome ; yes => don't bother with the dispose flag AWC.PB457
|
||
Move.L (A0),A0 ; dereference it AWC.PB457
|
||
BClr #DisposeBit,PmPrivate(A0) ; turn off the auto dispose AWC.PB457
|
||
GoHome Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE FindIndex; IMMEDIATE;
|
||
;
|
||
; On entry:
|
||
; A2 - Palette pointer
|
||
; A3 - ColorInfo
|
||
;
|
||
; On exit:
|
||
; D0 - index of animating entry; 0 if not found (0 is illegal for animation)
|
||
|
||
FindIndex PROC EXPORT
|
||
|
||
MoveM.L D3/D4,-(SP) ; save registers
|
||
Move ciPrivate(A3),D0 ; get link info
|
||
BfExtU D0{16:3},D1 ; grab top 3 bits
|
||
Cmp #4,D1 ; are they set correctly
|
||
Bne.S BadIndex ; no => the LinkInfo is invalid
|
||
Move.L PMgrHandle,A0 ; get main handle
|
||
CmpA.L #PMgrNil,A0 ; is it nil?
|
||
Beq.S BadIndex ; yes => punt
|
||
Move.L (A0),A0 ; dereference the palette manager
|
||
Move nDevs(A0),D3 ; get number of devices to search in D3
|
||
Beq.S BadIndex ; no devices => can't animate AWC.PB500
|
||
Lea DevHandles(A0),A1 ; point A1 at the device info stuff
|
||
Bra.S DevEnd ; jump into loop
|
||
|
||
DevLoop Move.L DevHandle(A1,D3.W*8),D4 ; get device handle
|
||
Cmp.L theGDevice,D4 ; is this it?
|
||
Beq.S FoundDevice ; yes => continue
|
||
DevEnd DBra D3,DevLoop ; no => look at another device
|
||
Bra.S BadIndex ; we fell through - punt
|
||
|
||
FoundDevice Move nDevs(A0),D4 ; get number of devices, this time as a watchdog
|
||
AddA.L #LinkTabs,A0 ; bump A0 to the base of LinkTabs
|
||
Bra.S IndexEnd ; start watchdog loop
|
||
|
||
IndexLoop BfExtU D0{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D0{24:8},D2 ; grab index number (0..255)
|
||
Cmp D3,D1 ; is it this device?
|
||
Beq.S FoundIndex ; yes => we've got it
|
||
Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Move ForeLink(A0,D1.L*4),D0 ; get next link; is the top bit set?
|
||
Bpl.S BadIndex ; no => stop because we ran out of tries
|
||
IndexEnd DBra D4,IndexLoop ; examine another index until our watchdog runs out
|
||
BadIndex Bra.S SetBadIndex ; set index to "illegal" AWC.PB377
|
||
|
||
; We found the index. Ensure that we don't exceed the bit depth, set "true" by returning
|
||
; a value <> 0.
|
||
|
||
FoundIndex And #$00FF,D2 ; clear everything except the index
|
||
Move D2,D0 ; set the result AWC.PB377
|
||
Move.L theGDevice,A0 ; get theGDevice AWC.PB377
|
||
Move.L (A0),A0 ; dereference it AWC.PB377
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap AWC.PB377
|
||
Move.L (A0),A0 ; dereference pixmap AWC.PB377
|
||
Move.L pmTable(A0),A0 ; get handle to CTab AWC.PB377
|
||
Move.L (A0),A0 ; dereference color table AWC.PB377
|
||
Cmp ctSize(A0),D0 ; compare link to maximum index AWC.PB377
|
||
Blt.S GoHome ; if D0-ctSize <= 0 then cool AWC.PB480
|
||
SetBadIndex MoveQ #0,D0 ; set index to "illegal" white AWC.PB377
|
||
GoHome MoveM.L (SP)+,D3/D4 ; restore registers
|
||
Rts ; go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE PmForeColor(dstEntry: INTEGER); INLINE $AA97;
|
||
;
|
||
|
||
PmForeColor PROC EXPORT
|
||
EXPORT PmBackColor
|
||
|
||
; In most cases we can rely upon RGBForeColor to do all the work for us. If a simple color,
|
||
; it's the perfect thing to call. If a true color, SetPalette did the important work for us
|
||
; and it's still correct. If it's an animating entry, we might not be on a device which can
|
||
; animate this color, so we want the foreground color preestablished so we can just quit if
|
||
; our attempt to use an animating entry fails.
|
||
;
|
||
; STAGE 2 - dithering patterns are not yet provided
|
||
|
||
ParamSize equ 2 ; total bytes of params
|
||
dstEntry equ ParamSize+8-2 ; which entry to use Palette handle
|
||
|
||
CallType equ -2 ; foreground = 1, background = 0
|
||
PWindow equ CallType-4 ; window pointer
|
||
GrafVarsPtr equ PWindow-4 ; GrafVars^
|
||
SrcPalette equ GrafVarsPtr-4 ; whichever palette we decide to use AWC.PB520
|
||
VarSize equ SrcPalette ; size of local variables AWC.PB520
|
||
|
||
MoveQ #1,D0 ; we're coming from PmForeColor
|
||
Bra.S PmSetColor ; share code
|
||
|
||
PmBackColor MoveQ #0,D0 ; we're coming from PmBackColor
|
||
|
||
PmSetColor Link A6,#VarSize ; build stack frame
|
||
MoveM.L A2-A3,-(SP) ; save registers
|
||
Move D0,CallType(A6) ; save the type of call
|
||
|
||
Move.L PMgrHandle,A1 ; get the main handle
|
||
CmpA.L #PMgrNil,A1 ; are we initialized?
|
||
Beq GoHome ; no => punt AWC.PB377
|
||
|
||
Move.L GrafGlobals(A5),A0 ; get the QuickDraw globals pointer
|
||
Move.L ThePort(A0),A0 ; point at the port
|
||
Tst PortBits+Rowbytes(A0) ; is it a new port?
|
||
Bpl GoHome ; no => punt AWC.PB377
|
||
|
||
Move.L A0,PWindow(A6) ; save it because we use it several times
|
||
Move.L GrafVars(A0),A0 ; get the data handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L A0,GrafVarsPtr(A6) ; save GrafVars pointer for later AWC.PB508
|
||
Move.L PmFgColor(A0),A2 ; get the palette handle (finally)
|
||
Move.L A2,D0 ; CmpA.L #Nil,A2; is there a palette? AWC.PB508
|
||
Bne.S FoundAPltt ; yes => we're cool so far AWC.PB508
|
||
Move.L AppPalette,A2 ; grab the AppPalette for use AWC.PB508
|
||
Move.L A2,D0 ; CmpA.L #Nil,A2; is there an AppPalette AWC.PB508
|
||
Beq GoHome ; no => punt AWC.PB508
|
||
FoundAPltt Move.L A2,SrcPalette(A6) ; save it so we can unlock it AWC.PB520
|
||
Move.L A2,A0 ; put the handle into A0 AWC.PB520
|
||
_HLock ; lock it down AWC.PB520
|
||
Move.L (A2),A2 ; dereference myPalette AWC.PB508
|
||
MoveQ #0,D0 ; clear the high word
|
||
Move dstEntry(A6),D0 ; capture the index
|
||
Cmp pmEntries(A2),D0 ; D0 - pmEntries; is myEntry out of range?
|
||
Bhs UnlockPltt ; yes, so we quit AWC.PB520
|
||
Asl.L #4,D0 ; multiply by record size of 16
|
||
Lea pmInfo(A2,D0.L),A3 ; set A3 to entry's ColorInfo
|
||
Pea ciRGB(A3) ; push address of ciRGB field
|
||
Tst CallType(A6) ; was it a background call
|
||
Bne.S DoForegrnd ; no => do the foreground call
|
||
_RGBBackColor ; yes => do the background call
|
||
Bra.S DoContinue ; keep going
|
||
|
||
DoForegrnd _RGBForeColor ; let this do almost all the work
|
||
DoContinue Move ciUsage(A3),D1 ; get flags
|
||
MoveQ #0,D0 ; clear high word
|
||
Move dstEntry(A6),D0 ; set D0 in case it is an explicit index
|
||
BTst #ExplicitBit,D1 ; is it explicit?
|
||
Bne.S DoExplicit ; yes => blast index into port
|
||
MoveQ #0,D0 ; set no error in case we go home
|
||
BTst #AnimatedBit,D1 ; no => test animation bit
|
||
Beq.S UnlockPltt ; yes => we're done AWC.PB520
|
||
Jsr FindIndex ; uses our registers - put reserved index in D0
|
||
Tst D0 ; was the result "white"?
|
||
Beq.S FixPort ; yes => give up, but set up the port first
|
||
Bra.S ShoveIndex ; share common code
|
||
|
||
DoExplicit Move.L theGDevice,A0 ; get theGDevice
|
||
Move.L (A0),A0 ; dereference it
|
||
Cmp #directType,gdType(A0) ; is it a direct device? AWC.PB530
|
||
Beq.S UnlockPltt ; yes => we're done AWC.PB530
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap
|
||
Move.L (A0),A0 ; dereference pixmap
|
||
Move.L pmTable(A0),A0 ; get handle to CTab
|
||
Move.L (A0),A0 ; dereference color table
|
||
And ctSize(A0),D0 ; and D0 with maximum index
|
||
|
||
ShoveIndex Move.L PWindow(A6),A0 ; get the window pointer again
|
||
Tst CallType(A6) ; foreground? AWC.PB377
|
||
Beq.S SetBackgrnd ; no => set background AWC.PB377
|
||
Move.L D0,FgColor(A0) ; jam the index
|
||
Bra.S FixPort ; continue AWC.PB377
|
||
|
||
SetBackgrnd Move.L D0,BkColor(A0) ; jam the index AWC.PB377
|
||
FixPort Move.L GrafVarsPtr(A6),A0 ; get the GrafVars pointer again
|
||
Tst CallType(A6) ; was it background?
|
||
Beq.S DoBackgrnd ; yes => set background information
|
||
Move dstEntry(A6),PmFgIndex(A0) ; save the entry number
|
||
BSet #PmFgBit,PmFlags+1(A0) ; tell the world that we set the FgColor
|
||
Bra.S UnlockPltt ; clean up and go home AWC.PB520
|
||
|
||
DoBackgrnd Move dstEntry(A6),PmBkIndex(A0) ; save the entry number
|
||
BSet #PmBkBit,PmFlags+1(A0) ; tell the world that we set the BkColor
|
||
UnlockPltt Move.L SrcPalette(A6),A0 ; get whichever palette we used AWC.PB520
|
||
_HUnlock ; unlock it AWC.PB520
|
||
GoHome MoveQ #0,D0 ; no error
|
||
MoveM.L (SP)+,A2-A3 ; restore register
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE AnimateEntry(dstWindow: WindowPtr; dstEntry: INTEGER; srcRGB: RGBColor); INLINE $AA99;
|
||
;
|
||
|
||
AnimateEntry PROC EXPORT
|
||
|
||
ParamSize equ 10 ; total bytes of params <AWC>
|
||
dstWindow equ ParamSize+8-4 ; target window <AWC>
|
||
dstEntry equ dstWindow-2 ; palette entry to animate <AWC>
|
||
srcRGB equ dstEntry-4 ; new color to use
|
||
|
||
SaveGDev equ -4 ; room for saving theGDevice
|
||
Mc equ SaveGDev-6 ; RGBColor
|
||
OldSeed equ Mc-4 ; old color table seed
|
||
VarSize equ OldSeed ; size of the variables
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3-D5/A2-A4,-(SP) ; save registers
|
||
|
||
Move.L PMgrHandle,A3 ; get the main handle
|
||
CmpA.L #PMgrNil,A3 ; are we initialized?
|
||
Beq GoHome ; no => punt AWC.PB377
|
||
|
||
Move.L dstWindow(A6),A0 ; get the target window
|
||
CmpA.L #Nil,A0 ; is it nil?
|
||
Beq GoHome ; yes => we're done AWC.PB377
|
||
|
||
Tst PortBits+Rowbytes(A0) ; is it a new port?
|
||
Bpl GoHome ; no => punt AWC.PB377
|
||
|
||
Move.L GrafVars(A0),A0 ; get the data handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L PmFgColor(A0),A2 ; get the palette handle (finally)
|
||
Move.L A2,D0 ; CmpA.L #Nil,A2; is there a palette? AWC.PB508
|
||
Bne.S FoundAPltt ; yes => use it AWC.PB508
|
||
Move.L AppPalette,A2 ; look for an AppPalette AWC.PB508
|
||
Move.L A2,D0 ; CmpA.L #Nil,A2; is there an AppPalette? AWC.PB508
|
||
Beq GoHome ; no => punt AWC.PB377
|
||
FoundAPltt Move.L (A2),A0 ; dereference the palette AWC.PB508
|
||
Move pmEntries(A0),D0 ; get the number of entries
|
||
MoveQ #0,D1 ; clear high word
|
||
Move dstEntry(A6),D1 ; get the index
|
||
Cmp D0,D1 ; is the index in range?
|
||
Bhs GoHome ; no => we're done AWC.PB377
|
||
|
||
Lsl #4,D1 ; multiply by ciSize
|
||
Lea pmInfo(A0,D1.L),A2 ; point A2 at the entry
|
||
BTst #ExplicitBit,ciUsage+1(A2) ; is it explicit?
|
||
Bne GoHome ; yes => by definition not animating
|
||
BTst #AnimatedBit,ciUsage+1(A2) ; is it animating?
|
||
Beq GoHome ; no => quit
|
||
|
||
; Copy the colors to the palette before we check to see if we have links or not so that it
|
||
; will get copied even if we have no 'clut' devices
|
||
|
||
Move.L srcRGB(A6),A0 ; get pointer to his RGB AWC.PB500
|
||
Move.L red(A0),D0 ; copy red and green AWC.PB500
|
||
Move.L D0,ciRGB+red(A2) ; copy it to the palette AWC.PB500
|
||
Move.L D0,mc+red(A6) ; save red and green on the stack AWC.PB500
|
||
Move blue(A0),D0 ; copy blue AWC.PB500
|
||
Move D0,ciRGB+blue(A2) ; copy it to the palette AWC.PB500
|
||
Move D0,mc+blue(A6) ; save blue on the stack AWC.PB500
|
||
|
||
Move ciPrivate(A2),D3 ; get the ForeLink field
|
||
BfExtu D3{16:3},D1 ; get the key bits
|
||
Cmp #4,D1 ; were they 100?
|
||
Bne GoHome ; no => not a valid ForeLink; go home
|
||
|
||
; Now, finally, we have something to do. Let's follow those links and see where they take us
|
||
|
||
Move.L A3,A0 ; copy PMgrHandle
|
||
_HLock ; lock it down
|
||
Move.L theGDevice,SaveGDev(A6) ; save it
|
||
|
||
; Register usage:
|
||
;
|
||
; D0 : holds ForeLink temporarily
|
||
; D3 : holds device number
|
||
; D4 : holds index number
|
||
; D5 : watchdog loop counter
|
||
;
|
||
; A2 : base address of LinkTabs
|
||
; A3 : PMgrHandle (locked)
|
||
; A4 : base address of DevHandles
|
||
|
||
Move.L (A3),A2 ; dereference PMgrHandle
|
||
Move nDevs(A2),D5 ; maximum number of devices (watchdog counter)
|
||
Lea DevHandles(A2),A4 ; point A4 at the device list
|
||
AddA.L #LinkTabs,A2 ; point A2 at start of LinkTabs
|
||
Move D3,D0 ; copy ForeLink into D0
|
||
Bra.S DevEnd ; jump into the loop
|
||
|
||
DevLoop BfExtU D0{19:5},D3 ; grab device number (0..31)
|
||
BfExtU D0{24:8},D4 ; grab index number (0..255)
|
||
Move.L DevHandle(A4,D3.W*8),A0 ; get the device handle
|
||
Move.L A0,theGDevice ; now we're on that device
|
||
Move.L (A0),A0 ; dereference it
|
||
Clr gdId(A0) ; no client id's, please
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap
|
||
Move.L (A0),A0 ; dereference pixmap
|
||
Move.L pmTable(A0),A0 ; get handle to CTab
|
||
Move.L (A0),A0 ; dereference CTab
|
||
Move ctSize(A0),D0 ; grab number of entries - 1
|
||
Cmp D4,D0 ; compare our index to the max index
|
||
Ble.S NextDevice ; out of range => look at next device AWC.PB480
|
||
Move.L ctSeed(A0),OldSeed(A6) ; save the seed so we can restore it
|
||
Move.L mc+red(A6),ctTable+RGB+red(A0,D4.W*8)
|
||
Move mc+blue(A6),ctTable+RGB+blue(A0,D4.W*8)
|
||
|
||
; Now perform a sequential _SetEntries using the device's color table as the source
|
||
|
||
Clr -(SP) ; push starting count of 0 for SetEntries
|
||
Move D0,-(SP) ; push number of entries-1
|
||
Pea ctTable(A0) ; push address of the first ColorSpec
|
||
_SetEntries ; do it
|
||
|
||
Move.L theGDevice,A0 ; get the device again
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap
|
||
Move.L (A0),A0 ; dereference pixmap
|
||
Move.L pmTable(A0),A0 ; get handle to CTab
|
||
Move.L (A0),A0 ; dereference CTab
|
||
Move.L OldSeed(A6),ctSeed(A0) ; we didn't really want it to change
|
||
|
||
NextDevice Lsl #8,D3 ; calculate offset to link table/4
|
||
Add D4,D3 ; offset to entry/4
|
||
Move ForeLink(A2,D3.L*4),D0 ; get next link; is the top bit set? AWC.PB500
|
||
DevEnd DBpl D5,DevLoop ; keep going until D0 is positive or D5 runs out
|
||
|
||
Move.L SaveGDev(A6),theGDevice ; restore theGDevice
|
||
Move.L A3,A0 ; copy PMgrHandle
|
||
_HUnlock ; unlock it
|
||
GoHome MoveQ #0,D0 ; no error AWC.PB377
|
||
MoveM.L (SP)+,D3-D5/A2-A4 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE AnimatePalette(dstWindow:WindowPtr; srcCTab: CTabHandle; srcIndex,
|
||
; dstEntry,dstLength: INTEGER; INLINE $AA9A;
|
||
;
|
||
|
||
AnimatePalette PROC EXPORT
|
||
|
||
ParamSize equ 14 ; total bytes of params <AWC>
|
||
dstWindow equ ParamSize+8-4 ; window to animate <AWC>
|
||
srcCTab equ dstWindow-4 ; new source colors
|
||
srcIndex equ srcCTab-2 ; first source entry to use
|
||
dstEntry equ srcIndex-2 ; first destination entry to set
|
||
dstLength equ dstEntry-2 ; how many to set
|
||
|
||
SaveGDev equ -4 ; room for saving theGDevice
|
||
SaveSeed equ SaveGDev-4 ; old color table seed
|
||
NumDev equ SaveSeed-2 ; copy of nDevs
|
||
DevCTabH equ NumDev-DevLimit*4 ; enough room for a CTabHandle per device
|
||
VarSize equ DevCTabH ; size of the variables
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3-D6/A2-A4,-(SP) ; save registers
|
||
|
||
Move.L PMgrHandle,A4 ; get the main handle
|
||
CmpA.L #PMgrNil,A4 ; are we initialized?
|
||
Beq GoHome ; no => punt AWC.PB377
|
||
|
||
Move.L dstWindow(A6),A0 ; get the target window <AWC>
|
||
CmpA.L #Nil,A0 ; is it nil? <AWC>
|
||
Beq GoHome ; yes => we're done AWC.PB377
|
||
|
||
Tst PortBits+Rowbytes(A0) ; is it a new port?
|
||
Bpl GoHome ; no => punt AWC.PB377
|
||
|
||
Move.L GrafVars(A0),A0 ; get the data handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L PmFgColor(A0),A2 ; get the palette handle (finally)
|
||
Move.L A2,D0 ; CmpA.L #Nil,A2; is there a palette? AWC.PB508
|
||
Bne.S FoundAPltt ; yes => use it AWC.PB508
|
||
Move.L AppPalette,A2 ; look for an AppPalette AWC.PB508
|
||
Move.L A2,D0 ; CmpA.L #Nil,A2; is there an AppPalette? AWC.PB508
|
||
Beq GoHome ; no => punt AWC.PB508
|
||
FoundAPltt Move.L srcCTab(A6),A3 ; get source color table AWC.PB508
|
||
Move.L A3,D0 ; CmpA.L #Nil,A3; is it nil? AWC.PB508
|
||
Beq GoHome ; yes => again punt AWC.PB377
|
||
|
||
Move.L (A2),A2 ; dereference the palette
|
||
Move pmEntries(A2),D0 ; get the number of entries; are there any?
|
||
Beq GoHome ; no => still punt AWC.PB377
|
||
MoveQ #0,D3 ; clear high word (so we can Lsl.L later)
|
||
Move dstEntry(A6),D3 ; get the starting index
|
||
Cmp D0,D3 ; is the start after the end?
|
||
Bhs GoHome ; yes => keep punting
|
||
|
||
Move.L (A3),A3 ; dereference the color table
|
||
Move srcIndex(A6),D4 ; get the starting index
|
||
Cmp ctSize(A3),D4 ; is the starting index within range?
|
||
Bhi GoHome ; no => once more, punt
|
||
|
||
; We have something worth copying! Now we can determine the length of the copy and
|
||
; place it in D5.
|
||
|
||
Sub D3,D0 ; calculate maximum length of a palette copy
|
||
Move D0,D5 ; save it in D5
|
||
Move ctSize(A3),D0 ; fetch the length of the color table
|
||
AddQ #1,D0 ; add 1 to make it 1-based
|
||
Sub D4,D0 ; calculate maximum length of a CTab copy
|
||
Cmp D0,D5 ; is D5 too big?
|
||
Bls.S NotTooBig ; no => don't replace it
|
||
Move D0,D5 ; copy smaller value to D5
|
||
NotTooBig Cmp dstLength(A6),D5 ; is D5 bigger than the request?
|
||
Bls.S StillOkay ; no => leave it alone
|
||
Move dstLength(A6),D5 ; copy smaller value to D5
|
||
StillOkay Move.L (A4),A1 ; dereference the palette manager handle
|
||
Move nDevs(A1),D0 ; put number of devices into D0
|
||
Move D0,NumDev(A6) ; remember number of devices
|
||
Lea DevHandles(A1),A4 ; point A4 at the clut device list AWC
|
||
Lea DevCTabH(A6),A0 ; point A0 at our temporary table AWC
|
||
Bra.S ClearEnd ; jump into loop
|
||
|
||
ClearLoop Clr.L (A0)+ ; clear room for a handle AWC
|
||
ClearEnd DBra D0,ClearLoop ; continue for nDevs devices AWC
|
||
|
||
AddA.L #LinkTabs,A1 ; bump A1 to the link tables
|
||
Lsl.L #4,D3 ; multiply D3 by ciSize
|
||
Lea pmInfo(A2,D3.L),A2 ; bump A2 to first ColorInfo
|
||
Lea ctTable(A3,D4.W*8),A3 ; bump A3 to first ColorSpec
|
||
Bra EntryEnd ; jump into loop
|
||
|
||
EntryLoop BTst #ExplicitBit,ciUsage+1(A2) ; is it explicit?
|
||
Bne.S NextEntry ; yes => by definition not animating AWC.PB500
|
||
BTst #AnimatedBit,ciUsage+1(A2) ; is it animating?
|
||
Beq.S NextEntry ; no => continue
|
||
Move.L RGB+red(A3),ciRGB+red(A2) ; copy red and green into palette
|
||
Move RGB+blue(A3),ciRGB+blue(A2) ; copy blue into palette
|
||
Move ciPrivate(A2),D0 ; get the ForeLink field
|
||
BfExtu D0{16:3},D1 ; get the key bits
|
||
Cmp #4,D1 ; were they 100?
|
||
Bne.S NextEntry ; no => not a valid ForeLink; go home
|
||
Move NumDev(A6),D6 ; get maximum number of devices to examine
|
||
SubQ #1,D6 ; decrement by 1 so we may fall through
|
||
|
||
; We fall through because the usual trick of branching to the end won't work when the
|
||
; end is a DBpl, not a DBf (DBra).
|
||
|
||
DevLoop BfExtU D0{19:5},D3 ; grab device number (0..31)
|
||
BfExtU D0{24:8},D4 ; grab index number (0..255)
|
||
Lea DevCTabH(A6),A0 ; point A0 at temporary table
|
||
Move.L (A0,D3.W*4),A0 ; get CTabHandle
|
||
CmpA.L #Nil,A0 ; have we seen this device yet?
|
||
Bne.S SeenDevice ; yes => skip setup
|
||
Move.L DevHandle(A4,D3.W*8),A0 ; get the device handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Clr gdId(A0) ; no client id's, please
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap
|
||
Move.L (A0),A0 ; dereference pixmap
|
||
Move.L pmTable(A0),D0 ; get handle to CTab
|
||
Lea DevCTabH(A6),A0 ; point A0 at temporary table
|
||
Move.L D0,(A0,D3.W*4) ; save it for later
|
||
Move.L D0,A0 ; copy CTabHandle back into A0 AWC PB223
|
||
SeenDevice Move.L (A0),A0 ; dereference CTab
|
||
Move ctSize(A0),D0 ; grab number of entries - 1
|
||
Cmp D4,D0 ; compare our index to the max index
|
||
Ble.S NextDevice ; out of range => look at next device AWC.PB480
|
||
Move.L ciRGB+red(A2),ctTable+RGB+red(A0,D4.W*8)
|
||
Move ciRGB+blue(A2),ctTable+RGB+blue(A0,D4.W*8)
|
||
NextDevice Lsl #8,D3 ; calculate offset to link table/4
|
||
Add D4,D3 ; offset to entry/4
|
||
Move ForeLink(A1,D3.L*4),D0 ; get next link; is the top bit set?
|
||
DevEnd DBpl D6,DevLoop ; keep going until D0 is positive or D5 runs out
|
||
|
||
NextEntry AddA.L #ciSize,A2 ; bump A2 to next ColorInfo
|
||
AddA.L #ColorSpecSize,A3 ; bump A3 to next ColorSpec
|
||
EntryEnd DBra D5,EntryLoop ; continue for all animating entries
|
||
|
||
Move.L theGDevice,SaveGDev(A6) ; save the old GDevice
|
||
Move NumDev(A6),D6 ; get number of devices to examine
|
||
Lea DevCTabH(A6),A2 ; point A2 at our temporary table
|
||
Bra.S SetEnd ; jump into loop
|
||
|
||
SetLoop Move.L (A2)+,A3 ; get next CTabHandle
|
||
CmpA.L #Nil,A3 ; did we initialize it?
|
||
Beq.S NextSet ; no => continue
|
||
Move.L DevHandle(A4),theGDevice ; put us on that device
|
||
Move.L (A3),A0 ; dereference it
|
||
Move.L ctSeed(A0),SaveSeed(A6) ; save the current seed
|
||
Clr -(SP) ; push starting count of 0 for SetEntries
|
||
Move ctSize(A0),-(SP) ; push number of entries-1
|
||
Pea ctTable(A0) ; push address of the first ColorSpec
|
||
_SetEntries ; do it
|
||
Move.L (A3),A0 ; dereference CTab again
|
||
Move.L SaveSeed(A6),ctSeed(A0) ; put the old seed back into place
|
||
NextSet AddQ.L #DevInfoSz,A4 ; bump A4 to the next device
|
||
SetEnd DBra D6,SetLoop ; loop for all devices
|
||
|
||
Move.L SaveGDev(A6),theGDevice ; restore the old GDevice
|
||
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
|
||
MoveM.L (SP)+,D3-D6/A2-A4 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE GetEntryColor(srcPalette: PaletteHandle; srcEntry: INTEGER; VAR dstRGB: RGBColor);
|
||
; INLINE $AA9B;
|
||
;
|
||
|
||
GetEntryColor PROC EXPORT
|
||
|
||
ParamSize equ 10 ; total bytes of params
|
||
srcPalette equ ParamSize+8-4 ; source Palette handle
|
||
srcEntry equ srcPalette-2 ; entry to get
|
||
dstRGB equ srcEntry-4 ; where to put color
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Move.L srcPalette(A6),A0 ; get palette
|
||
CmpA.L #Nil,A0 ; is it nil?
|
||
Beq.S GoHome ; yes => punt AWC.PB377
|
||
Move.L (A0),A0 ; dereference it
|
||
Move pmEntries(A0),D0 ; get the number of entries
|
||
MoveQ #0,D1 ; clear high word
|
||
Move srcEntry(A6),D1 ; get the index
|
||
Cmp D0,D1 ; is the index in range?
|
||
Bhs.S GoHome ; no => we're done AWC.PB377
|
||
Lsl.L #4,D1 ; multiply by number of records
|
||
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
|
||
Move.L dstRGB(A6),A1 ; get the destination
|
||
Move.L ciRGB+red(A0),red(A1) ; copy red and green
|
||
Move ciRGB+blue(A0),blue(A1) ; copy blue
|
||
GoHome MoveQ #0,D0 ; clear error condition
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE SetEntryColor(dstPalette: PaletteHandle; dstEntry: INTEGER; srcRGB: RGBColor);
|
||
; INLINE $AA9C;
|
||
;
|
||
|
||
SetEntryColor PROC EXPORT
|
||
|
||
ParamSize equ 10 ; total bytes of params
|
||
dstPalette equ ParamSize+8-4 ; source Palette handle
|
||
dstEntry equ dstPalette-2 ; entry to set
|
||
srcRGB equ dstEntry-4 ; new color
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Move.L dstPalette(A6),A0 ; get palette
|
||
CmpA.L #Nil,A0 ; is it nil?
|
||
Beq.S GoHome ; yes => punt AWC.PB377
|
||
Move.L (A0),A0 ; dereference it
|
||
Move pmEntries(A0),D0 ; get the number of entries
|
||
MoveQ #0,D1 ; clear high word
|
||
Move dstEntry(A6),D1 ; get the index
|
||
Cmp D0,D1 ; is the index in range?
|
||
Bhs.S GoHome ; no => we're done AWC.PB377
|
||
Lsl.L #4,D1 ; multiply by number of records
|
||
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
|
||
Move.L srcRGB(A6),A1 ; get the source
|
||
Move.L red(A1),ciRGB+red(A0) ; copy red and green
|
||
Move blue(A1),ciRGB+blue(A0) ; copy blue
|
||
Move.L dstPalette(A6),-(SP) ; push the palette handle AWC.PB508
|
||
Bsr DirtySeeds ; clear the device seeds AWC.PB508
|
||
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE GetEntryUsage(srcPalette: PaletteHandle; srcEntry: INTEGER; VAR dstUsage,
|
||
; dstTolerance: INTEGER); INLINE $AA9D;
|
||
;
|
||
|
||
GetEntryUsage PROC EXPORT
|
||
|
||
ParamSize equ 14 ; total bytes of params
|
||
srcPalette equ ParamSize+8-4 ; source Palette handle
|
||
srcEntry equ srcPalette-2 ; entry number
|
||
dstUsage equ srcEntry-4 ; where to put usage
|
||
dstTolerance equ dstUsage-4 ; where to put tolerance
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Move.L srcPalette(A6),A0 ; get palette
|
||
CmpA.L #Nil,A0 ; is it nil?
|
||
Beq.S GoHome ; yes => punt AWC.PB377
|
||
Move.L (A0),A0 ; dereference it
|
||
Move pmEntries(A0),D0 ; get the number of entries
|
||
MoveQ #0,D1 ; clear high word
|
||
Move srcEntry(A6),D1 ; get the index
|
||
Cmp D0,D1 ; is the index in range?
|
||
Bhs.S GoHome ; no => we're done AWC.PB377
|
||
Lsl.L #4,D1 ; multiply by number of records
|
||
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
|
||
Move.L dstUsage(A6),A1 ; get the destination
|
||
Move ciUsage(A0),(A1) ; copy usage
|
||
Move.L dstTolerance(A6),A1 ; get the second destination
|
||
Move ciTolerance(A0),(A1) ; copy tolerance
|
||
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE SetEntryUsage(dstPalette: PaletteHandle; dstEntry,srcUsage,srcTolerance: INTEGER);
|
||
; INLINE $AA9E;
|
||
;
|
||
|
||
SetEntryUsage PROC EXPORT
|
||
|
||
ParamSize equ 10 ; total bytes of params
|
||
dstPalette equ ParamSize+8-4 ; source Palette handle
|
||
dstEntry equ dstPalette-2 ; entry number
|
||
srcUsage equ dstEntry-2 ; new usage
|
||
srcTolerance equ srcUsage-2 ; new tolerance
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Move.L dstPalette(A6),A0 ; get palette
|
||
CmpA.L #Nil,A0 ; is it nil?
|
||
Beq.S GoHome ; yes => punt AWC.PB377
|
||
Move.L (A0),A0 ; dereference it
|
||
Move pmEntries(A0),D0 ; get the number of entries
|
||
MoveQ #0,D1 ; clear high word
|
||
Move dstEntry(A6),D1 ; get the index
|
||
Cmp D0,D1 ; is the index in range?
|
||
Bhs.S GoHome ; no => we're done AWC.PB377
|
||
Lsl.L #4,D1 ; multiply by number of records
|
||
Lea pmInfo(A0,D1.L),A0 ; point A0 at the correct ColorInfo
|
||
Move srcUsage(A6),ciUsage(A0) ; copy usage
|
||
Move srcTolerance(A6),ciTolerance(A0) ; copy tolerance
|
||
Move.L dstPalette(A6),-(SP) ; push the palette handle AWC.PB508
|
||
Bsr DirtySeeds ; clear the device seeds AWC.PB508
|
||
GoHome MoveQ #0,D0 ; clear error condition AWC.PB377
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE CTab2Palette(srcCTab: CTabHandle; dstPalette: PaletteHandle; myUsage,
|
||
; myTolerance: INTEGER); INLINE $AA9F;
|
||
;
|
||
|
||
CTab2Palette PROC EXPORT
|
||
|
||
ParamSize equ 12 ; total bytes of params
|
||
srcCTab equ ParamSize+8-4 ; source ColorTable handle
|
||
dstPalette equ srcCTab-4 ; destination Palette handle
|
||
srcUsage equ dstPalette-2 ; default usage value
|
||
srcTolerance equ srcUsage-2 ; default usage tolerance
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3/A2-A3,-(SP) ; save registers
|
||
|
||
Move.L dstPalette(A6),A2 ; get palette
|
||
CmpA.L #Nil,A2 ; is it nil?
|
||
Beq.S GoHome ; can't deal with nil here either AWC.PB377
|
||
|
||
Move.L dstPalette(A6),-(SP) ; push Palette
|
||
Jsr ClearPalette ; clear animating entries and seed handle
|
||
Bne.S GoHome ; if not zero it was a bad palette AWC.PB457
|
||
|
||
Move.L srcCTab(A6),A3 ; get color table
|
||
CmpA #Nil,A3 ; is it nil?
|
||
Beq.S GoHome ; can't deal with a nil handle AWC.PB377
|
||
Move.L (A3),A1 ; dereference it
|
||
MoveQ #0,D3 ; clear high word of D3
|
||
Move ctSize(A1),D3 ; get size-1 of CTab
|
||
AddQ #1,D3 ; D3 is number of entries in palette
|
||
|
||
Move.L A2,A0 ; copy myPalette handle
|
||
Move.L D3,D0 ; copy size
|
||
AddQ #1,D0 ; include palette header
|
||
Asl #4,D0 ; multiply by 16 bytes per entry | header
|
||
_SetHandleSize ; do it
|
||
Bne.S GoHome ; and quit if we couldn't do it AWC.PB377
|
||
|
||
Move.L A2,-(SP) ; push the palette handle AWC.PB508
|
||
Bsr DirtySeeds ; clear the device seeds AWC.PB508
|
||
Move.L (A2),A0 ; dereference our handle
|
||
Move D3,pmEntries(A0) ; copy size
|
||
AddA.L #pmInfo,A0 ; bump us to the first ColorInfo
|
||
|
||
Move.L (A3),A1 ; dereference source handle again
|
||
AddQ.L #ctTable,A1 ; bump A1 to the first ColorSpec
|
||
Move srcUsage(A6),D1 ; grab myUsage from parameters
|
||
Swap D1 ; put it in high word
|
||
Move srcTolerance(A6),D1 ; grab myTolerance into low word
|
||
Bra.S CopyEnd ; jump into DBra loop
|
||
|
||
CopyLoop Move.L RGB+red(A1),ciRGB+red(A0) ; copy red and green
|
||
Move RGB+blue(A1),ciRGB+blue(A0) ; copy blue
|
||
Move.L D1,ciUsage(A0) ; copy myUsage and myTolerance
|
||
Clr ciFlags(A0) ; clear private flags
|
||
Clr.L ciPrivate(A0) ; clear private links
|
||
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
|
||
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
|
||
CopyEnd DBra D3,CopyLoop ; decrement and branch until copy is done
|
||
GoHome MoveQ #0,D0 ; clear error AWC.PB377
|
||
MoveM.L (SP)+,D3/A2-A3 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE Palette2CTab(srcPalette: PaletteHandle; dstCTab: CTabHandle); INLINE $AAA0;
|
||
;
|
||
|
||
Palette2CTab PROC EXPORT
|
||
|
||
ParamSize equ 8 ; total bytes of params
|
||
srcPalette equ ParamSize+8-4 ; source Palette handle
|
||
dstCTab equ srcPalette-4 ; destination CTabHandle
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3/A2-A3,-(SP) ; save registers
|
||
|
||
; first grab MyPalette and myCTab and compare them to nil
|
||
|
||
Move.L srcPalette(A6),A2 ; get source into A2
|
||
CmpA #Nil,A2 ; is it nil?
|
||
Beq.S GoHome ; punt if no palette AWC.PB377
|
||
Move.L dstCTab(A6),A3 ; get destination into A3
|
||
CmpA #Nil,A3 ; is it nil?
|
||
Beq.S GoHome ; punt if no ctab AWC.PB377
|
||
|
||
; leave size in D0; dereference both handles and capture pmEntries
|
||
|
||
Move.L (A2),A0 ; dereference myPalette
|
||
MoveQ #0,D3 ; clear high word
|
||
Move pmEntries(A0),D3 ; get number of palette entries
|
||
Move.L D3,D0 ; copy length
|
||
AddQ.L #1,D0 ; add 1 for the header
|
||
Lsl.L #3,D0 ; multiply by size of ColorSpec
|
||
Move.L A3,A0 ; put handle in A0
|
||
_SetHandleSize ; resize it
|
||
Bne.S GoHome ; <> 0 => couldn't handle it AWC.PB377
|
||
|
||
Move.L (A2),A0 ; redereference myPalette
|
||
Move.L (A3),A1 ; dereference CTab
|
||
Move D3,D0 ; copy size to a temp
|
||
SubQ #1,D0 ; ctSize is really last entry
|
||
|
||
; CHECK - what should we do with the seed? Get name of call from Ernie, again.
|
||
|
||
Clr.L ctSeed(A1) ; clear seed
|
||
Move D0,ctSize(A1) ; set size
|
||
Clr transIndex(A1) ; this is not a device ColorTable (clear hi bit)
|
||
AddQ #ctTable,A1 ; bump color table to start
|
||
AddA #pmInfo,A0 ; bump palette to start
|
||
MoveQ #0,D1 ; clear index for pixel value
|
||
Bra.S CopyEnd ; jump to start of copy
|
||
|
||
CopyLoop Move D1,value(A1) ; set pixel value
|
||
Move.L ciRGB(A0),RGB(A1) ; copy red and green
|
||
Move ciRGB+blue(A0),RGB+blue(A1) ; copy blue
|
||
AddA.L #ciSize,A0 ; bump A0 to next ColorInfo
|
||
AddQ.L #ColorSpecSize,A1 ; bump A1 to next ColorSpec
|
||
AddQ #1,D1 ; bump pixel value
|
||
CopyEnd DBra D3,CopyLoop ; loop for all entries
|
||
GoHome MoveQ #0,D0 ; clear error condition
|
||
MoveM.L (SP)+,D3/A2-A3 ; restore registers <AWC>
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE ClearOne(eInfo:CiInfo; BasePtr:Ptr); LOCAL;
|
||
;
|
||
|
||
ClearOne PROC EXPORT
|
||
|
||
ParamSize equ 4 ; total bytes of params
|
||
eInfo equ ParamSize+8-4 ; entry to clear
|
||
BasePtr equ eInfo-4 ; pointer to PMgrHandle^^
|
||
|
||
VarSize equ 0
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
Move.L A2,-(SP) ; save a register
|
||
Move.L eInfo(A6),A0 ; get the ColorInfo address
|
||
Move.L CiPrivate(A0),D0 ; get the current link information
|
||
Clr ciFlags(A0) ; shut down any crap
|
||
Clr.L ciPrivate(A0) ; clear it
|
||
Move.L BasePtr(A6),A1 ; set up DevListPtr
|
||
Lea DevHandles(A1),A2 ; A2 points at DevHandles
|
||
AddA.L #LinkTabs,A1 ; A1 points at LinkTabs
|
||
NextLink BfExtU D0{19:5},D1 ; grab device number (0..31)
|
||
BfExtU D0{24:8},D2 ; grab index number (0..255)
|
||
Move.L (A2,D1.W*8),A0 ; get the device handle
|
||
Move.L (A0),A0 ; dereference it
|
||
Move.L gdPMap(A0),A0 ; get handle to pixmap
|
||
Move.L (A0),A0 ; dereference pixmap
|
||
Move.L pmTable(A0),A0 ; get handle to CTab
|
||
Move.L (A0),A0 ; dereference CTab
|
||
Cmp ctSize(A0),D2 ; is index number <= entries - 1?
|
||
Bhi.S IgnoreIt ; no => don't unreserve it
|
||
Clr ctTable+value(A0,D2.W*8) ; unreserve it
|
||
IgnoreIt Lsl #8,D1 ; calculate offset to link table/4
|
||
Add D2,D1 ; offset to entry/4
|
||
Lea (A1,D1.L*4),A0 ; point A0 at next forward link
|
||
Move ForeLink(A0),D0 ; get next link
|
||
Clr.L ForeLink(A0) ; clear it for the next guy
|
||
Tst D0 ; is there another link to examine?
|
||
Bmi.S NextLink ; yes => go unlink it
|
||
Move.L (SP)+,A2 ; restore A2
|
||
Unlk A6 ; clean up our mess
|
||
Rtd #ParamSize ; go home
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE CopyPalette(srcPalette,dstPalette: PaletteHandle; srcEntry,dstEntry,dstLength:
|
||
; INTEGER); INLINE $AAA1;
|
||
;
|
||
|
||
CopyPalette PROC EXPORT
|
||
|
||
ParamSize equ 14 ; total bytes of params
|
||
srcPalette equ ParamSize+8-4 ; source Palette handle
|
||
dstPalette equ srcPalette-4 ; destination palette handle
|
||
srcEntry equ dstPalette-2 ; source starting entry
|
||
dstEntry equ srcEntry-2 ; destination starting entry
|
||
dstLength equ dstEntry-2 ; length of the copy
|
||
|
||
TrimLen equ -2
|
||
VarSize equ TrimLen
|
||
|
||
Link A6,#VarSize ; build stack frame
|
||
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
|
||
|
||
Move.L PMgrHandle,A4 ; get the main handle
|
||
CmpA.L #PMgrNil,A4 ; are we initialized?
|
||
Beq GoHome ; no => punt AWC.PB377
|
||
|
||
Move.L dstPalette(A6),A2 ; get destination palette
|
||
CmpA.L #Nil,A2 ; is it nil?
|
||
Beq GoHome ; can't deal with nil here either AWC.PB377
|
||
|
||
Move.L srcPalette(A6),A3 ; get source palette
|
||
CmpA.L #Nil,A3 ; is it nil?
|
||
Beq GoHome ; can't deal with a nil handle AWC.PB377
|
||
|
||
CmpA.L A2,A3 ; does source = destination?
|
||
Beq GoHome ; we can't handle this yet AWC.PB377
|
||
|
||
MoveQ #0,D0 ; clear D0
|
||
Move dstLength(A6),D0 ; get the length of the copy
|
||
Ble GoHome ; we can quit if it's too small
|
||
Move.L D0,D3 ; copy the length
|
||
Add SrcEntry(A6),D0 ; D0 is the required length of the source
|
||
|
||
Move.L (A3),A1 ; dereference source palette
|
||
Move pmEntries(A1),D1 ; get size of source palette
|
||
Sub D0,D1 ; D1, if negative, is how much we must trim D3
|
||
Bpl.S DontTrimSrc ; no => don't trim it
|
||
Add D1,D3 ; trim back the length of the copy AWC.PB530
|
||
DontTrimSrc Move.L (A2),A0 ; dereference the destination
|
||
Move pmEntries(A0),D4 ; get the length
|
||
Move DstEntry(A6),D0 ; calculate the potential new pmEntries
|
||
Add D3,D0 ; by adding the trimmed length
|
||
Cmp D4,D0 ; need we add handle room?
|
||
Ble.S BigEnough ; no => skip _SetHandleSize AWC.PB530
|
||
|
||
Move D0,D4 ; save new length
|
||
Move.L A2,A0 ; copy DstPalette
|
||
AddQ #1,D0 ; include palette header
|
||
Asl #4,D0 ; multiply by 16 bytes per entry | header
|
||
_SetHandleSize ; do it
|
||
Bne GoHome ; and quit if we couldn't do it AWC.PB377
|
||
|
||
Move.L (A2),A0 ; dereference the destination handle
|
||
Move D4,D2 ; make a copy of the new length
|
||
MoveQ #0,D1 ; clear the high word
|
||
Move PmEntries(A0),D1 ; this is where to start clearing
|
||
Sub D1,D2 ; this is now many to clear
|
||
Move D4,pmEntries(A0) ; save size
|
||
Lea PmInfo(A0),A1 ; point us at the start of the table
|
||
Asl #4,D1 ; this is the offset to the start of the clear
|
||
AddA.L D1,A1 ; bump A1 to the start of the clear
|
||
Bra.S ClearEnd ; jump to the DBra
|
||
|
||
; The main reason for clearing is so we can correctly detect and clear entries that are
|
||
; going to be clobbered.
|
||
|
||
ClearLoop Clr.L (A1)+ ; clear 16 bytes
|
||
Clr.L (A1)+
|
||
Clr.L (A1)+
|
||
Clr.L (A1)+
|
||
ClearEnd DBra D2,ClearLoop
|
||
|
||
BigEnough CmpA.L A2,A3 ; does SrcPalette = DstPalette?
|
||
Beq.S GoHome ; yes => can't handle this AWC.PB377
|
||
Move.L A3,-(SP) ; push the palette handle AWC.PB508
|
||
Bsr DirtySeeds ; clear the device seeds AWC.PB508
|
||
Move.L (A3),A1 ; dereference source palette
|
||
MoveQ #0,D0 ; clear the high word
|
||
Move DstEntry(A6),D0 ; get the first destination
|
||
Asl.L #4,D0 ; multiply by 16
|
||
Move.L (A2),A0 ; dereference destination palette again AWC.PB508
|
||
Lea PmInfo(A0,D0),A0 ; point A0 at the first destination
|
||
MoveQ #0,D1 ; clear the high word
|
||
Move SrcEntry(A6),D0 ; get the first source
|
||
Asl.L #4,D0 ; point A0 at the first destination
|
||
Lea PmInfo(A1,D0),A1 ; point A1 at the first source
|
||
Bra.S CopyEnd ; jump into the loop
|
||
|
||
CopyLoop Move.L ciPrivate(A0),D0 ; get the link info
|
||
Beq.S NoLinks ; no => it doesn't need clearing
|
||
MoveM.L A0-A1,-(SP) ; save registers
|
||
Move.L A0,-(SP) ; ciInfo to clear
|
||
Move.L (A4),-(SP) ; dereference PMgrHandle and push it
|
||
Jsr ClearOne ; clear the links
|
||
MoveM.L (SP)+,A0-A1 ; restore interesting registers
|
||
|
||
NoLinks Move.L ciRGB(A1),ciRGB(A0) ; copy first two words
|
||
Move.L ciRGB+Blue(A1),ciRGB+blue(A0) ; copy blue and usage
|
||
Move ciTolerance(A1),ciTolerance(A0) ; copy tolerance
|
||
Clr ciFlags(A0) ; clear the flags field
|
||
Clr.L ciPrivate(A0) ; clear the links field
|
||
AddA.L #CiSize,A0 ; bump both pointers
|
||
AddA.L #CiSize,A1
|
||
CopyEnd DBra D3,CopyLoop ; loop for (trimmed) length entries
|
||
GoHome MoveQ #0,D0 ; clear error code AWC.PB377
|
||
MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
|
||
; Thus ends the PaletteManager - ah, a sad thing it is, to be done. But WAIT! There's
|
||
; MORE! Let's patch RGBFORECOLOR and RGBBACKCOLOR just for grins! Yeah!
|
||
|
||
IF not ROMPaletteMgr THEN ; no patches for the ROM version RWH.C864
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure RGBForeColor (Color : RGBColor);
|
||
;
|
||
; This routine takes an RGB triple and sets the current Graf- or CGrafPort
|
||
; fields so that drawing will take place with the best match of the
|
||
; requested color, using the current GDevice's color matching rules. The
|
||
; appropriate fields are set depending on portType
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBForeColor) (RGBForeColor)
|
||
|
||
RGBForeColor PROC EXPORT
|
||
EXPORT RGBBackColor,RGB2OLD
|
||
|
||
StdDevCall Equ $1D2A0 ; RGBForeColor; RGBBackColor is $4081D2B0 <PB302>
|
||
StdDevMask Equ $FFFFFFEF ; the calls are different only at bit 4!
|
||
|
||
MOVEQ #FGCOLOR,D0 ; get offset to index field
|
||
MOVEQ #RGBFgColor,D1 ; get offset to RGB field
|
||
|
||
SHARE MOVE.L 4(SP),A1 ; point at the RGB color
|
||
MOVE.L GRAFGLOBALS(A5),A0 ; get the QuickDraw globals pointer
|
||
MOVE.L THEPORT(A0),A0 ; point at the port
|
||
PEA 0(A0,D0) ; save pointer to the index field
|
||
|
||
TST PORTBITS+ROWBYTES(A0) ; is it a new port?
|
||
BMI.S NEWPORT ; => yes, set RGB components
|
||
JSR RGB2OLD ; else convert RGB to old color
|
||
BRA DONE ; =>
|
||
|
||
; To keep the stack correct we will momentarily preempt A1. We can restore it in a bit.
|
||
; Also, since we no longer need the offset to the index field
|
||
|
||
NewPort Move.L GrafVars(A0),A1 ; get the GrafVars handle
|
||
CmpA.L #Nil,A1 ; is it nil?
|
||
Beq.S PuntPmCalls ; yes => punt and do the normal call
|
||
Move.L (A1),A1 ; dereference it into A1
|
||
Move.L 4(SP),D2 ; get the return address
|
||
Sub.l ROMBase, D2 ; Make it offset within ROM, <PB302>
|
||
And.L #StdDevMask,D2 ; and it with the std mask
|
||
Cmp.L #StdDevCall,D2 ; is it from StdDevLoop?
|
||
Bne.S NormalCall ; no => make the normal call
|
||
Tst.L PmFgColor(A1) ; is there a palette? EHB.PBnnn
|
||
Bne.S FoundAPltt ; yes => we can do it AWC.PB508
|
||
Tst.L AppPalette ; is there an AppPalette? AWC.PB508
|
||
Beq.S NormalCall ; => no, do normal call EHB.PBnnn
|
||
FoundAPltt Move PmFlags(A1),D2 ; get the Palette Manager flags AWC.PB508
|
||
Cmp #FgColor,D0 ; was it forecolor?
|
||
Bne.S GetBack ; no => get back color flag
|
||
|
||
BTst #PmFgBit,D2 ; did PmForeColor set up this port?
|
||
Beq.S PuntPmCalls ; no => continue normally
|
||
AddQ #4,SP ; we won't need the pointer to the index
|
||
Move pmFgIndex(A1),-(SP) ; push the entry number
|
||
_PmForeColor ; set the port using PmForeColor
|
||
Bra.S GoHome ; all finished
|
||
|
||
GetBack BTst #PmBkBit,D2 ; did PmBackColor set up this port?
|
||
Beq.S PuntPmCalls ; no => continue normally
|
||
AddQ #4,SP ; we won't need the pointer to the index
|
||
Move pmBkIndex(A1),-(SP) ; push the entry number
|
||
_PmBackColor ; set the port using PmBackColor
|
||
Bra.S GoHome ; all through
|
||
|
||
NormalCall Move PmFlags(A1),D2 ; get flags
|
||
Cmp #FgColor,D0 ; is this a foreground call?
|
||
Bne.S NotFgCall ; no => clear PmBkBit
|
||
BClr #PmFgBit,D2 ; clear the foreground flag bit
|
||
Bra.S CommonFlags ; reunite it
|
||
|
||
NotFgCall BClr #PmBkBit,D2 ; clear the background flag bit
|
||
CommonFlags Move D2,PmFlags(A1) ; save the flags to GrafVars
|
||
PuntPmCalls Move.L 8(SP),A1 ; restore the pointer to the RGBColor
|
||
|
||
; Here is the normal RGBForeColor code code
|
||
|
||
MOVE.L red(A1),red(A0,D1) ; copy red and green components to the port
|
||
MOVE.W blue(A1),blue(A0,D1) ; and blue too
|
||
|
||
; make an rgbColor on the stack
|
||
|
||
MOVE.L green(A1),-(SP) ; copy green and blue
|
||
MOVE.W red(A1),-(SP) ; copy red
|
||
SUBQ #4,SP ; make room for function return
|
||
PEA 4(SP) ; push pointer to rgb
|
||
_Color2Index ; convert it to an index
|
||
|
||
MOVE.L (SP)+,D0 ; get the index result
|
||
ADDQ #6,SP ; get rid of the rgbColor
|
||
|
||
Done MOVE.L (SP)+,A0 ; get pointer to index field
|
||
MOVE.L D0,(A0) ; and set the index field
|
||
GoHome Rtd #4 ; all done
|
||
|
||
RGB2OLD
|
||
;-----------------------------------------------
|
||
;
|
||
; UTILITY TO CONVERT AN RGB (POINTED TO BY A1) VALUE
|
||
; TO AN OLD STYLE COLOR VALUE. RETURNS VALUE IN D0. CLOBBERS A0,D1
|
||
;
|
||
; USES HIGH BIT OF EACH COMPONENT TO SELECT RGB OFF (0) OR ON (1)
|
||
|
||
MOVEQ #0,D1 ; clear out D1
|
||
MOVE (A1)+,D1 ; get red
|
||
LSL.L #1,D1 ; get high bit
|
||
MOVE (A1)+,D1 ; get green
|
||
LSL.L #1,D1 ; get high bit
|
||
MOVE (A1)+,D1 ; get blue
|
||
LSL.L #1,D1 ; get high bit
|
||
SWAP D1 ; get RGB index
|
||
|
||
noBlue LEA MapTbl,A0 ; get translate table
|
||
MOVEQ #0,D0 ; clear out high word
|
||
MOVE 0(A0,D1*2),D0 ; convert to planar value
|
||
RTS ; => all done
|
||
|
||
; TABLE TO MAP FROM 3 BIT RGB TO OLD-STYLE COLOR INDICES
|
||
|
||
MapTBL DC.W blackColor ; RBG = 0,0,0 -> black
|
||
DC.W blueColor ; RBG = 0,0,1 -> blue
|
||
DC.W greenColor ; RBG = 0,1,0 -> green
|
||
DC.W cyanColor ; RBG = 0,1,1 -> cyan
|
||
DC.W redColor ; RBG = 1,0,0 -> red
|
||
DC.W magentaColor ; RBG = 1,0,1 -> magenta
|
||
DC.W yellowColor ; RBG = 1,1,0 -> yellow
|
||
DC.W whiteColor ; RBG = 1,1,1 -> white
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure RGBBackColor (Color : RGBColor);
|
||
;
|
||
; This routine takes an RGB triple and sets the current Graf- or CGrafPort
|
||
; fields so that drawing will take place with the best match of the
|
||
; requested color, using the current GDevice's color matching rules. The
|
||
; appropriate fields are set depending on portType.
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (RGBBackColor) (RGBBackColor)
|
||
|
||
RGBBackColor
|
||
|
||
MOVEQ #BKCOLOR,D0 ; get offset to the index field
|
||
MOVEQ #RGBBkColor,D1 ; get offset to RGB field
|
||
BRA SHARE ; => and use common code
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure myNewCWindow()
|
||
;
|
||
; Initialize the palette manager fields of the new window.
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewCWindow) (myNewCWindow)
|
||
|
||
myNewCWindow PROC EXPORT
|
||
|
||
ROMNewCWindow EQU $0F9F6 ; normal NewCWindow routine <PB302>
|
||
|
||
; shuffle parameters so it will return to us
|
||
|
||
MOVE.L SP,A0 ; get src for params
|
||
MOVE.L SP,A1 ; get dst for params
|
||
MOVE.L (A0)+,D1 ; save RTS
|
||
MOVEQ #7,D0 ; move 8 longs
|
||
@NxtLong MOVE.L (A0)+,(A1)+ ; move a long
|
||
DBRA D0,@NxtLong ; repeat for all longs
|
||
MOVE.L D1,30(SP) ; stuff original RTS
|
||
|
||
JSRROM ROMNewCWindow ; call NewCWindow <PB302>
|
||
|
||
; always set the default palette to 0
|
||
|
||
MOVE.L (SP),A1 ; get the window
|
||
MOVE.L GrafVars(A1),A0 ; get handle to vars
|
||
MOVE.L (A0),A0 ; point to vars
|
||
CLR.L PMFgColor(A0) ; and clear palette
|
||
MOVE.L (SP)+,A1 ; get window pointer
|
||
MOVE.L (SP),A0 ; get return address
|
||
MOVE.L A1,(SP) ; stuff wPtr
|
||
JMP (A0) ; and return
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure myNewWindow();
|
||
;
|
||
; When NewWindow is called, do an ActivatePalette in case there's a default palette.
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (NewWindow) (myNewWindow)
|
||
|
||
myNewWindow PROC EXPORT
|
||
|
||
ROMNewWindow EQU $0FA08 ; normal NewWindow routine <PB302>
|
||
|
||
; shuffle parameters so it will return to us
|
||
|
||
MOVE.L SP,A0 ; get src for params
|
||
MOVE.L SP,A1 ; get dst for params
|
||
MOVE.L (A0)+,D1 ; save RTS
|
||
MOVEQ #7,D0 ; move 8 longs
|
||
@NxtLong MOVE.L (A0)+,(A1)+ ; move a long
|
||
DBRA D0,@NxtLong ; repeat for all longs
|
||
MOVE.L D1,30(SP) ; stuff original RTS
|
||
|
||
JSRROM ROMNewWindow ; call NewWindow <PB302>
|
||
|
||
MOVE.L (SP),-(SP) ; push the window
|
||
_ActivatePalette ; and activate the system palette
|
||
|
||
@DONE MOVE.L (SP)+,A1 ; get window pointer
|
||
MOVE.L (SP),A0 ; get return address
|
||
MOVE.L A1,(SP) ; stuff wPtr
|
||
JMP (A0) ; and return
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure HiliteWindow();
|
||
;
|
||
; Patch HiliteWindow to call ActivatePalette if called from SelectWindow
|
||
; AND if it is not called from MoveWindow!
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (HiliteWindow) (myHiliteWindow)
|
||
|
||
myHiliteWindow PROC EXPORT
|
||
|
||
FromSelect EQU $1016A ; RTS if called from select <PB302>
|
||
FromMove EQU $10396 ; RTS if selected from Move <PB302>
|
||
ROMHilite EQU $0FFCE ; real HiliteWindow <PB302>
|
||
|
||
CMPRA FromSelect,(SP) ; from selectWindow? <PB302>
|
||
BNE.S @JustHilite ; => no, just hilite
|
||
CMPRA FromMove,$38(SP) ; from Move? <PB302>
|
||
BEQ.S @JustHilite ; => yes, just hilite
|
||
TST.B 4(SP) ; hiliting?
|
||
BEQ.S @JustHilite ; => no, just (un)hilite
|
||
LEA 6(SP),A0 ; point to window
|
||
MOVE.L (A0),-(SP) ; push window
|
||
MOVE -(A0),-(SP) ; push boolean
|
||
JSRROM ROMHilite ; call hilite in ROM <PB302>
|
||
|
||
MOVE.L 6(SP),-(SP) ; push window pointer
|
||
_ActivatePalette ; and activate its palette
|
||
RTD #6 ; strip 6 bytes params and return
|
||
|
||
@JustHilite JMPROM ROMHilite ; and complete the call <PB302>
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure MyMoveWindow
|
||
;
|
||
; Patch MoveWindow to call ActivatePalette
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MoveWindow) (myMoveWindow)
|
||
|
||
MyMoveWindow PROC EXPORT
|
||
|
||
ROMMove EQU $0FD9C ; real MoveWindow <PB302>
|
||
|
||
LEA 10(SP),A0 ; point to window
|
||
MOVE.L (A0),-(SP) ; push window
|
||
MOVE.L -(A0),-(SP) ; push dst location
|
||
MOVE -(A0),-(SP) ; push frontflag
|
||
JSRROM ROMMove ; call movewindow <PB302>
|
||
|
||
MOVE.L 10(SP),-(SP) ; push window
|
||
_ActivatePalette ; and activate its palette
|
||
RTD #10 ; strip 10 bytes and return
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure MySizeWindow
|
||
;
|
||
; Patch SizeWindow to call MySetPalette
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (SizeWindow) (mySizeWindow)
|
||
|
||
MySizeWindow PROC EXPORT
|
||
|
||
ROMSize EQU $1000E ; real SizeWindow <PB302>
|
||
|
||
LEA 10(SP),A0 ; point to window
|
||
MOVE.L (A0),-(SP) ; push window
|
||
MOVE.L -(A0),-(SP) ; push dst location
|
||
MOVE -(A0),-(SP) ; push frontflag
|
||
JSRROM ROMSize ; call SizeWindow <PB302>
|
||
|
||
MOVE.L 10(SP),-(SP) ; push window
|
||
_ActivatePalette ; and activate its palette
|
||
RTD #10 ; strip 10 bytes and return
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure MyClose
|
||
;
|
||
; Patch CloseWindow to call DisposPalette. In the initial system disk release, this
|
||
; patch mistakenly operated on DisposeWindow instead of CloseWindow.
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (CloseWindow) (myClose)
|
||
|
||
MyClose PROC EXPORT
|
||
|
||
ROMClose EQU $0FB6E ; real CloseWindow <PB302>
|
||
|
||
MOVE.L 4(SP),A0 ; get the window
|
||
TST PORTBITS+ROWBYTES(A0) ; is it new?
|
||
BPL.S @NotNew ; => no
|
||
|
||
MOVE.L GrafVars(A0),A0 ; get grafVar handle
|
||
MOVE.L (A0),A0 ; point at grafVars
|
||
MOVE.L PmFgColor(A0),D0 ; is there a palette
|
||
BEQ.S @NotNew ; => no
|
||
|
||
Move.L D0,A0 ; let's use an address register AWC.PB457
|
||
Move.L (A0),A0 ; dereference it AWC.PB457
|
||
BTst #DisposeBit,pmPrivate(A0) ; should we dispose of it? AWC.PB457
|
||
Beq.S @NotNew ; no => the user has to dispose of it AWC.PB457
|
||
|
||
MOVE.L D0,-(SP) ; else push palette
|
||
_DisposePalette ; and dump it
|
||
|
||
@NotNew JMPROM ROMClose ; and dispose the window <PB302>
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure MyShowHide();
|
||
;
|
||
; Patch MyShowHide to call ActivatePalette. If it is being called to show a hidden window,
|
||
; then do the ActivatePalette.
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (ShowHide) (myShowHide)
|
||
|
||
MyShowHide PROC EXPORT
|
||
|
||
ROMShow EQU $0F742 ; real MoveWindow <PB302>
|
||
|
||
TST.B 4(SP) ; is it show?
|
||
BEQ.S @NoShow ; =>no, no go show
|
||
|
||
MOVE.L 6(SP),A0 ; get the window
|
||
TST.B WVisible(A0) ; is it showtime
|
||
BNE.S @NoShow ; =>no, not yet
|
||
|
||
LEA 6(SP),A0 ; point to window
|
||
MOVE.L (A0),-(SP) ; push window
|
||
MOVE -(A0),-(SP) ; push marquis
|
||
JSRROM ROMShow ; call showwindow <PB302>
|
||
|
||
MOVE.L A1,-(SP) ; save A1 for ShowHide!
|
||
MOVE.L 10(SP),-(SP) ; push window
|
||
_ActivatePalette ; and activate its palette
|
||
MOVE.L (SP)+,A1 ; restore A1 for ShawHide
|
||
RTD #6 ; strip 10 bytes and return
|
||
|
||
@NoShow JMPROM ROMShow ; the ROM must begin <PB302>
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; procedure MyExit;
|
||
;
|
||
; Patch MyExit to call DisposePalette for all palettes in the app heap. In addition, jam
|
||
; theGDevice and srcDevice with MainDevice. As if that weren't enough, make sure that
|
||
; cursor interrupts are enabled.
|
||
;
|
||
; This patch is not installed by A/UX or under MultiFinder.
|
||
;
|
||
; AppleSystemPatch PaletteMgr.a 10Mar87 #PB103 (MyExit) (myExit)
|
||
|
||
MyExit PROC EXPORT
|
||
|
||
EXPORT myExitExit ; address of JMP target to daisy chain <PB158>
|
||
|
||
ROMIAZInit EQU $4080DEF8 ; jump back into ROM
|
||
ROMAppZoneAddr EQU $4080D434 ; a useful routine
|
||
|
||
MOVEM.L A0-A3/D0-D3,-(SP) ; save all registers
|
||
MOVE.L PMgrHandle,A2 ; get paletteMgr handle
|
||
CMP.L MinusOne,A2 ; is it there?
|
||
BEQ.S GoHome ; => no, just return
|
||
MOVE.L (A2),A1 ; point to data structure
|
||
MOVE.L PListHandle(A1),A0 ; get handle to palette list
|
||
_HLock ; and lock it down
|
||
MOVE.L (A0),A3 ; point to palette list
|
||
|
||
Move APalettes(A1),D3 ; get number of active handles
|
||
Beq.s NoPals ; no friends => go home
|
||
Add FreeSpaces(A1),D3 ; calculate total number of entries
|
||
Clr.L WindowList ; clear the list of windows for FrontWindow AWC.PB506
|
||
BRA.S FindEnd ; => check for no entries
|
||
|
||
FindLoop Move.L PaletteRef(A3),D1 ; get first entry
|
||
BEQ.S FindNext ; => no palette in entry
|
||
MOVE.L D1,D0 ; and get for routine
|
||
JSR ROMAppZoneAddr ; in application area (or zero)? <C699>
|
||
BNE.S FindNext ; => not in app heap
|
||
MOVE.L D1,-(SP) ; push palette handle
|
||
_DisposePalette ; and dispose it in place
|
||
FindNext AddQ #PLstEntrySz,A3 ; bump to the next entry
|
||
FindEnd DBra D3,FindLoop ; repeat for all spaces
|
||
|
||
NoPals MOVE.L (A2),A1 ; point to palette stuff
|
||
MOVE.L PListHandle(A1),A0 ; get handle to palette list
|
||
_HUnlock ; and unlock it
|
||
|
||
GoHome Clr.L AppPalette ; set us up for the next guy AWC.PB508
|
||
MOVE.L MainDevice,A0 ; get the main device
|
||
MOVE.L A0,SrcDevice ; set the src device
|
||
MOVE.L A0,theGDevice ; and the current device
|
||
|
||
MOVE #$2000,SR ; make sure interrupts enabled
|
||
|
||
MOVEM.L (SP)+,A0-A3/D0-D3 ; restore all registers
|
||
JMP $4080000A ; jump to next code in chain <PB158>
|
||
myExitExit EQU *-4 ; address of JMP target <PB158>
|
||
|
||
ENDIF ; end of patches commented out for ROM RWH.C864
|
||
|
||
; Okay, that's it. We're out of here!
|
||
|