mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-11-19 06:30:59 +00:00
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!
|
|
|