mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-12-13 11:29:15 +00:00
2682 lines
104 KiB
Plaintext
2682 lines
104 KiB
Plaintext
;
|
||
; Hacks to match MacOS (most recent first):
|
||
;
|
||
; <Sys7.1> 8/3/92 Elliot make this change
|
||
; 9/2/94 SuperMario ROM source dump (header preserved below)
|
||
;
|
||
|
||
;
|
||
; File: ColorMgr.a
|
||
;
|
||
; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM8> 11/7/93 SAM Changed GetCTable to get a new seed if the id > 1023 (kMinSeed).
|
||
; <SM6> 9/13/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
|
||
; so they can conditionalized out of the build.
|
||
; <SM4> 1/21/93 KW (LW3 fau) Rolled in the MySaveEntries patch: In SaveEntries, if
|
||
; the bpp is ≥ 16bpp it will exit with an error, but the code was
|
||
; not returning the stack to it's correct state. Renamed all the
|
||
; labels in SaveEntries that started with a SE to SaveEnt so they
|
||
; don't clash with the ones in SetEntries, that also start with
|
||
; SE.
|
||
; <SM3> 12/19/92 HI Modified GetCTable to copy the 'clut' resources instead of
|
||
; just detaching the resource handle because sometimes GetCTable
|
||
; modifies the 'clut' but it can't sice the SuperMario 'clut'
|
||
; resource overrides the System file's resource. Hence a RAM copy
|
||
; of the ROM's 'clut' resource must be made. This fixes the bug
|
||
; of machine freezing when switching to 16 colors. (Hoon Im)
|
||
; <SM2> 6/11/92 stb <sm 6/9/92>stb add comments from QDciPatchROM.a to MakeITable,
|
||
; AdjZone, Collapse, NewHandleTempSysApp, Index2Color,
|
||
; InvertColor, DelSearch, DelComp; this file is synched with
|
||
; QDciPatchROM.a
|
||
; <16> 1/18/91 dvb Don't restore color environment if it hasn't been changed.
|
||
; Modify SetEntries to mark flag in QDSpare.
|
||
; <15> 11/6/90 KON GetCTable should return NIL if call fails. This is at an offset
|
||
; of 6, not 8. [SMC]
|
||
; <14> 10/29/90 KON If GetCTable fails, it should return NIL. There were cases where
|
||
; it returned without setting the return value at all.
|
||
; <13> 9/17/90 BG Removed <10>. 040s are now behaving more reliably.
|
||
; <12> 8/21/90 KON No need to _HLock and _HUnlock search element handle in
|
||
; Color2Index.
|
||
; <11> 7/24/90 gbm change a duplicate symbol or two
|
||
; <10> 6/25/90 BG Added EclipseNOPs to deal with flakey 040s.
|
||
; <9> 5/29/90 KON Make DelSearch and DelComp jive with ci patch.
|
||
; <8> 5/29/90 KON Call Translate24to32 on addresses passed to DelSearch and
|
||
; DelComp so they match the addresses in the gDevice.
|
||
; <7> 3/26/90 KON Use NewHandle,sys rather than change zone when getting memory
|
||
; for ITable. Fix comp proc bug in _InvertColor.
|
||
; <6> 3/2/90 KON If app heap is the same as sys heap, only check for memory once.
|
||
; <5> 3/1/90 KON Change MakeITable so it first looks in Tmp memory, then in sys
|
||
; memory, and finally theZone for memory.
|
||
; <4> 1/31/90 BAL Fixed replication of 5 bit components in Index2Color to use the
|
||
; same algorithm as Search16toIndexed (stretch.a) in order to make
|
||
; SeedCFill/CalcCMask happy.
|
||
; <3> 1/30/90 DAF Removed CLUTBusy asynchronous flags from SetEntries. They
|
||
; didn't work well and broke Studio/8.
|
||
; <2> 1/16/90 BAL Changed MakeITab to restore theZone during error returns.
|
||
; <•2.3> 7/14/89 BAL For Aurora: Final CQD
|
||
; <2.2> 6/30/89 BAL GetCTable will not modify 2 bit CLUT if hilite color is a gray.
|
||
; ∂
|
||
; <2.1> 6/15/89 BAL Changed source to use ReserveBit instead of Reserve; Fixed bug
|
||
; in makeGray tab.
|
||
; <2.0> 6/12/89 BAL Added ; to 1.9
|
||
; <1.9> 6/12/89 BAL Stopped Color2Index,Index2Color from clearing QDErr. Rolled in
|
||
; fix to MyGetCTable.
|
||
; <1.8> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
|
||
; file (colorequ.a), got rid of QuickDraw nFiles dependencies and
|
||
; fixed up necessary files…
|
||
; <•1.7> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
|
||
; <1.6> 5/15/89 DAF Corrected GetCTable (actually myGetCTable) to always return a
|
||
; non-purgeable cTabHandle
|
||
; 5/14/89 DAF Fixed GetCTable to return non-purgeable handle if from system
|
||
; resource.
|
||
; <1.5> 4/20/89 GGD Fixed assembly error (missing semicolon) so that the ROMs can
|
||
; build again.
|
||
; <1.4> 4/19/89 DAF Rolled in system disk patch to SetEntries (additional error
|
||
; checking).
|
||
; 4/19/89 DAF Rolled in SaveEntries patch from system file.
|
||
; <•1.3> 4/12/89 BAL Blasting in 32-Bit QuickDraw 1.0B1
|
||
; 4/5/89 DAF Added additional error checking to RestoreEntries.
|
||
; 4/24/87 DAF Fixed MakeITable not to SysError on memory failures (from
|
||
; romfix78)
|
||
; <C835> 2/20/87 DAF MakeITable gets queue sizes from a resource now. Exported
|
||
; ITabMatch and vector to it from Color2Index. ReserveEntry
|
||
; changes ctSeed when deactivating reserve bit.
|
||
; <C824> 2/15/87 DAF Fixed displacement into hidden color table in ITabMatch to work
|
||
; correctly in 5-bit res mode.
|
||
; <C777> 2/9/87 DAF Reactivated usage of .value fields for protect, reserve and
|
||
; ownerID. Made ReserveEntry change ctSeed.
|
||
; <C751> 2/3/87 DAF Separated ProtErr test for protect and reserve in SetEntries
|
||
; (err only if .value field doesn't match clientID. Adjusted
|
||
; ReserveEntry to set clientID when reserve=TRUE. Added range and
|
||
; protection error checking to SetCommon. Adjusted seeding code in
|
||
; MakeITable for common loop for single loop exit, and to seed
|
||
; original colors in a different order.
|
||
; <C733> 2/2/87 DAF Fixed MakeITable to test if result table can be allocated early,
|
||
; so it doesn't need to SysError, and cleaned up zone setting.
|
||
; SetEntries now returns a ProtErr when attempting to change
|
||
; reserved entries. RealColor fixed to compare only iTable
|
||
; resolution bits of each channel. Updated error codes throughout.
|
||
; <C695> 1/26/87 DAF Made _Control calls immediate. Added range-checking for res and
|
||
; default color- and inverse tables to MakeITable
|
||
; <C666> 1/22/87 DAF Fixed trashed registers in MakeSubTable. Changed searchProc
|
||
; chain to be handles instead of pointers. Added
|
||
; DeleteSearch,DeleteComp routines.
|
||
; <C645> 1/15/87 DAF Fixed 5-Bit ITable building by expanding TblSize to a long
|
||
; <C575> 12/30/86 DAF Made some minor bug fixes to SetCommon and MakeITable
|
||
; <C491> 12/6/86 DAF Made fixes from code review. Changed interfaces of
|
||
; Color2Index,Index2Color, and SetEntry (now SetEntries)
|
||
; <C387> 11/9/86 DAF Refined Save/RestoreEntries (added reqLSize field), improved
|
||
; error handling added QDErr routine.
|
||
; <C348> 11/4/86 DAF Added Save/RestoreEntries
|
||
; <C294> 10/26/86 DAF Updated SetEntry to call video driver
|
||
; <C241> 10/20/86 DAF Fixed TFB CLUT address temporarily
|
||
; <C239> 10/19/86 DAF Added ITSeed to inverse tables. Made ITabMatch rebuild invalid
|
||
; iTable
|
||
; 10/13/86 EHB Delete packCLUT and unpackCLUT. No packed CLUTs!
|
||
; <C367> 10/7/86 DAF Removed temp patches in SetEntry
|
||
; 10/5/86 DAF Added a number of unimplemented routines
|
||
; 8/12/86 EHB Added CTSeed field to color tables built by unpackClut
|
||
; 8/12/86 EHB INIT VALUE FIELD TO ENTRY NUMBER
|
||
; 7/24/86 DAF New today
|
||
;
|
||
; To Do:
|
||
;
|
||
|
||
;EASE$$$ READ ONLY COPY of file “ColorMgr.a”
|
||
;•2.3 BAL 07/14/1989 For Aurora: Final CQD
|
||
; 2.2 BAL 06/30/1989 GetCTable will not modify 2 bit CLUT if hilite color is a gray. ∂
|
||
;Changed MakeITable to use MFTemp memory if allocation of its work buffer in the app heap fails.∂
|
||
;If MakeITable returns an error, ITabMatch will use the stale inverse table instead of aborting.
|
||
; 2.1 BAL 06/15/1989 Changed source to use ReserveBit instead of Reserve; Fixed bug in makeGray tab.
|
||
; 2.0 BAL 06/12/1989 Added ; to 1.9
|
||
; 1.9 BAL 06/12/1989 Stopped Color2Index,Index2Color from clearing QDErr. Rolled in fix to MyGetCTable.
|
||
; 1.8 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.7 BAL 05/29/1989 Blasting in 32-Bit QuickDraw version 1.0 Final
|
||
; 1.6 DAF 05/15/1989 Corrected GetCTable (actually myGetCTable) to always
|
||
; return a non-purgeable cTabHandle
|
||
; 1.5 GGD 04/20/1989 Fixed assembly error (missing semicolon) so that the ROMs can
|
||
; build again.
|
||
; 1.4 DAF 04/19/1989 Rolled in system disk patch to SetEntries (additional
|
||
; error checking).
|
||
;•1.3 BAL 04/12/1989 Blasting in 32-Bit QuickDraw 1.0B1
|
||
|
||
;
|
||
; File ColorMgr.a
|
||
;
|
||
; Copyright Apple Computer, Inc. 1981-1986
|
||
; All Rights Reserved
|
||
;
|
||
;
|
||
;------------------------------------------
|
||
;
|
||
; Color Manager
|
||
;
|
||
; This code provides services for matching RGB color specifications to
|
||
; color look-up table indices, implements the device-independent layer
|
||
; of functions such as setting color table entries, and includes
|
||
; some useful utilities for dealing with pixelmaps.
|
||
;
|
||
; Modification History:
|
||
; ----------------------------
|
||
;
|
||
; 24-Jul-86 DAF New today
|
||
; 12AUG86 EHB INIT VALUE FIELD TO ENTRY NUMBER
|
||
; 12Aug86 EHB Added CTSeed field to color tables built by unpackClut
|
||
; 05Oct86 DAF Added a number of unimplemented routines
|
||
; 13oct86 EHB Delete packCLUT and unpackCLUT. No packed CLUTs!
|
||
;<C239/19Oct86> DAF Added ITSeed to inverse tables. Made ITabMatch rebuild
|
||
; invalid iTable
|
||
;<C241/20Oct86> DAF Fixed TFB CLUT address temporarily
|
||
;<C294/26Oct86> DAF Updated SetEntry to call video driver
|
||
;<C348/04Nov86> DAF Added Save/RestoreEntries
|
||
;<C367/07Oct86> DAF Removed temp patches in SetEntry
|
||
;<C387/09Nov86> DAF Refined Save/RestoreEntries (added reqLSize field), improved error handling
|
||
; added QDErr routine.
|
||
;<C491/06Dec86> DAF Made fixes from code review. Changed interfaces of Color2Index,Index2Color,
|
||
; and SetEntry (now SetEntries)
|
||
;<C575/30Dec86> DAF Made some minor bug fixes to SetCommon and MakeITable
|
||
;<C645/15Jan87> DAF Fixed 5-Bit ITable building by expanding TblSize to a long
|
||
;<C666/22Jan87> DAF Fixed trashed registers in MakeSubTable. Changed searchProc chain to be
|
||
; handles instead of pointers. Added DeleteSearch,DeleteComp routines.
|
||
;<C695/26Jan87> DAF Made _Control calls immediate. Added range-checking for res and default
|
||
; color- and inverse tables to MakeITable
|
||
;<C733/02Feb87> DAF Fixed MakeITable to test if result table can be allocated early, so it
|
||
; doesn't need to SysError, and cleaned up zone setting. SetEntries now
|
||
; returns a ProtErr when attempting to change reserved entries. RealColor
|
||
; fixed to compare only iTable resolution bits of each channel. Updated
|
||
; error codes throughout.
|
||
;<C751/03Feb87> DAF Separated ProtErr test for protect and reserve in SetEntries (err only if
|
||
; .value field doesn't match clientID. Adjusted ReserveEntry to set clientID
|
||
; when reserve=TRUE. Added range and protection error checking to SetCommon.
|
||
; Adjusted seeding code in MakeITable for common loop for single loop
|
||
; exit, and to seed original colors in a different order.
|
||
;<C777/09Feb87> DAF Reactivated usage of .value fields for protect, reserve and ownerID. Made
|
||
; ReserveEntry change ctSeed.
|
||
;<C824/15Feb87> DAF Fixed displacement into hidden color table in ITabMatch to work correctly
|
||
; in 5-bit res mode.
|
||
;<C835/20Feb87> DAF MakeITable gets queue sizes from a resource now. Exported ITabMatch
|
||
; and vector to it from Color2Index. ReserveEntry changes ctSeed when
|
||
; deactivating reserve bit.
|
||
;_______________________________________________________________________
|
||
;
|
||
; Post Mac II Release
|
||
;_______________________________________________________________________
|
||
;
|
||
; <24Apr87> DAF Fixed MakeITable not to SysError on memory failures (from romfix78)
|
||
;_______________________________________________________________________
|
||
;
|
||
; The Colorful World of 32-bit QuickDraw
|
||
;
|
||
; <05Apr89> DAF Added additional error checking to RestoreEntries.
|
||
; <19Apr89 DAF Rolled in SaveEntries patch from system file.
|
||
; <14May89> DAF Fixed GetCTable to return non-purgeable handle if from
|
||
; system resource.
|
||
; <30Jan98 DAF Removed CLUTBusy change-blocking flag in SetEntries
|
||
;_______________________________________________________________________
|
||
|
||
|
||
MACHINE MC68020
|
||
|
||
;---------------------------
|
||
; TEMPORARY EXPORTS OF UNIMPLEMENTED ROUTINES.
|
||
|
||
UPDATEPIXMAP PROC EXPORT
|
||
RTS
|
||
|
||
;
|
||
; QUEUE and DEQUEUE : macro definitions for circular queue maintainance, as
|
||
; used by MakeITable. They expect : A4 = queue insertion pointer
|
||
; A5 = end of queue memory
|
||
; A1 = queue removal pointer
|
||
; QStart(A6) = start of queue memory
|
||
; D0 is trashed
|
||
|
||
MACRO
|
||
QUEUE ®1,®2 ;
|
||
CMP.L A4,A5 ; is it time to wrap?
|
||
BNE.S @88 ; nope, so continue
|
||
MOVE.L QStart(A6),A4 ; wrap back
|
||
@88 MOVE.L ®1,D0 ; copy it to D0
|
||
ADD.L ®2,D0 ; and add the other reg
|
||
MOVE.W D0,(A4)+ ; put it in the queue
|
||
ENDM
|
||
|
||
MACRO
|
||
DEQUEUE ® ;
|
||
CMP.L A1,A5 ; is it time to wrap?
|
||
BNE.S @97 ; nope, so continue
|
||
MOVE.L QStart(A6),A1 ; wrap back
|
||
@97 CMP.L A4,A1 ; is it done?
|
||
BNE.S @98 ; not done, so get a displacement
|
||
MOVEQ #0,® ; return the completion signal
|
||
BRA.S @99 ;
|
||
@98 MOVE.W (A1)+,® ; get the next displacement
|
||
@99
|
||
ENDM
|
||
|
||
|
||
MakeITable PROC EXPORT
|
||
EXPORT MakeGrayITab
|
||
;----------------------------------------------------------------
|
||
;
|
||
; PROCEDURE MakeITable (CTABH: CTabHandle; ITabH: ITabHandle; res:integer);
|
||
;
|
||
; This procedure builds an inverse lookup table with res bits per channel
|
||
; based on the specified color table. Algorithm by MJ Potel, based on Voronoi theory.
|
||
; Algorithm modified by Art Cabral, adding a linked list at the end of the table
|
||
; which is used to find hidden colors in Color2Index.
|
||
;
|
||
; Still to be done : Consolidate Queue and table into 1 memory block
|
||
; Convert to bitmap/iLUT form
|
||
; Eliminate BTST for TST.B
|
||
;
|
||
; 1. Use supplied cTabHandle and iTabHandle. This makes it context independent.
|
||
; 2. Compress directly into iTable. A little faster.
|
||
; 3. Shouldn't need to to error checking in QUEUE and DEQUEUE
|
||
|
||
; contains the fix from QDciPatchROM.a to first search temp memory, then system <sm 6/9/92>stb
|
||
; zone, then finally theZone. <sm 6/9/92>stb
|
||
|
||
UNDEF EQU $8000 ; hi bit on
|
||
BOUND EQU $7FFF ; non-neg, large unused index
|
||
|
||
QInTempBit EQU $00
|
||
ITableInTempBit EQU $01
|
||
|
||
PARAMSIZE EQU 10 ; total bytes of params
|
||
CTabH EQU PARAMSIZE+8-4 ; Color table handle
|
||
ITabH EQU CTabH-4 ; ITable handle
|
||
RES EQU ITabH-2 ; entry size
|
||
|
||
QStart EQU -4 ; pointer to the queue
|
||
SvZone EQU QStart-4 ; save the current zone
|
||
TblH EQU SvZone-4 ; copy of our temp ITable
|
||
TblSize EQU TblH-4 ; size of our temp ITable
|
||
InfoOffset EQU TblSize-4 ; offset to ITInfoTable from ITabH
|
||
isTmpHandle EQU InfoOffset-2 ; boolean->true if TblH is a TmpMem handle
|
||
QHandle EQU isTmpHandle-4 ; Handle for queue <28Feb90 KON>
|
||
VARSIZE EQU QHandle
|
||
|
||
|
||
LINK A6,#VARSIZE ; set up a stack frame
|
||
MOVEM.L A2-A5/D3-D7,-(SP) ; save 'em all
|
||
; move.l theZone,SvZone(A6) ; save the current heap zone for later restore <16Jan90> BAL
|
||
|
||
CLR.W QDErr ; clear QDError flag <C666/22Jan87> DAF
|
||
|
||
MOVE res(A6),D7 ; get the channel size <C777/12Feb87> EHB
|
||
CMP.L #-1,theGDevice ; if -1, then it's uninitialized <C777/12Feb87> DAF
|
||
BEQ.S @ResCheck ; OK, so continue <C777/12Feb87> DAF
|
||
|
||
@GDevOK
|
||
MOVE.L ([theGDevice]),A0 ; get a pointer to the current device <C777/12Feb87> DAF
|
||
|
||
; test the parameters. If ITabH or CTabH are NIL, substitute handles from theGDevice <C695/26Jan87> DAF
|
||
|
||
TST.L ITabH(A6) ; is ITabH NIL? <C695/26Jan87> DAF
|
||
BNE.S @DoCTabH ; no, so continue <C695/26Jan87> DAF
|
||
MOVE.L GDITable(A0),ITabH(A6) ; stick theGDevice's ITabH in stack frame <C695/26Jan87> DAF
|
||
|
||
@DoCTabH
|
||
|
||
TST.L CTabH(A6) ; is CTabH NIL? <C695/26Jan87> DAF
|
||
BNE.S @DoITabRes ; no, so continue <C695/26Jan87> DAF
|
||
MOVE.L ([GDPMap,A0]),A1 ; get pixMap's handle <C695/26Jan87> DAF
|
||
MOVE.L PMTable(A1),CTabH(A6) ; get the device colorTable's pointer <C695/26Jan87> DAF
|
||
|
||
@DoITabRes
|
||
|
||
; get the ITable resolution
|
||
|
||
TST D7 ; test the channel size <C777/09Feb87> EHB
|
||
BNE.S @ResCheck ; if valid, continue <C695/26Jan87> DAF
|
||
|
||
; the res parameter was 0, so get theGDevice's preferred resolution <C777/09Feb87> DAF
|
||
MOVE.W GDResPref(A0),D7 ; get the preferred ITabRes <C695/26Jan87> DAF
|
||
BNE.S @ResSubst ; if non-zero, then continue <C777/09Feb87> DAF
|
||
MOVEQ #4,D7 ; if resPref=0, then force to 4 <C777/09Feb87> DAF
|
||
@ResSubst
|
||
MOVE.W D7,res(A6) ; and put it in the stack frame <C695/26Jan87> DAF
|
||
|
||
@ResCheck
|
||
CMP.W #2,D7 ; don't accept res≤2 <C695/26Jan87> DAF
|
||
BLE.S @BadRes ; <C695/26Jan87> DAF
|
||
CMP.W #6,D7 ; or ≥ 6 <C695/26Jan87> DAF
|
||
BLT.S @ResOK ; <C695/26Jan87> DAF
|
||
|
||
@BadRes MOVE.W #cResErr,QDErr ; mark the error and quit <C695/26Jan87> DAF
|
||
BRA MITDone ; <C695/26Jan87> DAF
|
||
@ResOK ; <C695/26Jan87> DAF
|
||
|
||
; Calculate the size of the compressed table and verify the handle
|
||
|
||
MOVE D7,D1 ; get the channel size <C733/02Feb87> DAF
|
||
MOVEQ.L #1,D0 ; prime the register
|
||
LSL.L D1,D0 ; calculate 2^^res
|
||
LSL.L D1,D0 ; square it
|
||
LSL.L D1,D0 ; cube it
|
||
ADD.L #ITTable,D0 ; make room for everybody
|
||
MOVE.L D0,InfoOffset(A6) ; save offset to end of table
|
||
ADD.L #ITExtraSize,D0 ; make room for InfoTable
|
||
|
||
MOVE.L ITabH(A6),A0 ; get the ITable handle
|
||
TST.L (A0) ; is the table purged? <C751/03Feb87> DAF
|
||
BEQ.S @1 ; yes, so Realloc it <C751/03Feb87> DAF
|
||
_SetHandleSize ; set the size <C751/03Feb87> DAF
|
||
BRA.S @2 ; and continue <C751/03Feb87> DAF
|
||
@1
|
||
_ReallocHandle ; <C751/03Feb87> DAF
|
||
@2
|
||
BEQ.S @SizeOK ; => size ok, so continue <C733/02Feb87> DAF
|
||
MOVE.W #CNoMemErr,QDErr ; report this error <C733/02Feb87> DAF
|
||
BRA MITDone ; and quit <C733/02Feb87> DAF
|
||
|
||
@SizeOK
|
||
;--------------------------------------------------------------------- <BAL 15Mar89>
|
||
;
|
||
; Cruise through the clut and check if all non-reserved entries are grays.
|
||
; If they are then build a gray Itab and set flag in Info header to indicate grayness.
|
||
;
|
||
|
||
move.l CTabH(a6),a0 ;
|
||
move.l (a0),a0 ; get CTab ptr
|
||
move.w ctSize(a0),d0 ; get clut entries-1
|
||
lea ctTable(a0),a1 ; point at first clut entry
|
||
|
||
@nextEntry
|
||
move.l (a1)+,d1 ; pick up value,red
|
||
move.l (a1)+,d2 ; pick up green,blue
|
||
cmp.w d1,d2 ; red==blue?
|
||
bne.s @notGray ;
|
||
swap d2 ; get green
|
||
cmp.w d1,d2 ; red==green?
|
||
bne.s @notGray ;
|
||
@skippy dbra d0,@nextEntry ; continue checking
|
||
|
||
_MakeGrayITab ; go make special Gray ITab
|
||
bra MITDone ; all done
|
||
|
||
@notGray
|
||
btst #ReserveBit+24,d1 ; is this entry reserved?
|
||
bne.s @skippy ; don't check reserved entries
|
||
|
||
;--------------------------------------------------------------------- <BAL 15Mar89>
|
||
|
||
AdjZone
|
||
|
||
; this is where the patch used to move.w #8080 to force the call to DisposeTempBuffer, <sm 6/9/92>stb
|
||
; but now, having had the opportunity to fix the code elsewhere, we don’t have to be <sm 6/9/92>stb
|
||
; so tricky, and we can go back to the normal way of doing things. <sm 6/9/92>stb
|
||
|
||
move.w #0,isTmpHandle(a6) ;assume handles are not in temp memory <28Feb90 KON>
|
||
|
||
; allocate space on the heap for the queue, reading queue size from resource
|
||
|
||
SUBQ #4,SP ; make room for the function return <C835/20Feb87> DAF
|
||
MOVE.L #'mitq',-(SP) ; push the queue size resource type <C835/20Feb87> DAF
|
||
CLR.W -(SP) ; want mitq=0 <C835/20Feb87> DAF
|
||
_rGetResource ; system first, then ROM <C835/20Feb87> DAF
|
||
MOVE.L (SP)+,A0 ; get the handle <C835/20Feb87> DAF
|
||
|
||
MOVE.L (A0),A0 ; get the pointer in A0 <C835/20Feb87> DAF
|
||
MOVE.L -12(A0,D7*4),D0 ; get the queue size (adjust for no 1 or 2 bit resolutions) <C835/20Feb87> DAF
|
||
MOVE.L D0,D3 ; hold it for a second
|
||
bsr NewHandleTempSysApp ;get memory <28Feb90 KON>
|
||
BNE MakeIErrLate ; if there was an error report it
|
||
;
|
||
; Got a handle. Check which heap it's in and lock it.
|
||
;
|
||
tst.w d1 ;d1=0 -> memory in temp heap <28Feb90 KON>
|
||
bne.s @notTemp1 ; <28Feb90 KON>
|
||
bset #QInTempBit, isTmpHandle(a6) ;Main ITable is in temp memory <28Feb90 KON>
|
||
@notTemp1
|
||
;
|
||
; want a ptr, so lock and deref handle
|
||
;
|
||
move.l a0,QHandle(a6) ;save QHandle <28Feb90 KON>
|
||
_HLock ;preserves a0 <28Feb90 KON>
|
||
move.l (a0),a0 ;deref it <28Feb90 KON>
|
||
|
||
MOVE.L A0,QStart(A6) ; save the starting addr in stack frame
|
||
ADD.L D3,A0 ; compute the addr of the queue end
|
||
MOVE.L A0,A5 ; keep the queue end here
|
||
|
||
; allocate BIG space on the heap for the ITable (to be shrunken and moved to sysheap later)
|
||
|
||
MOVEQ #1,D6 ; prime the register
|
||
LSL.L D7,D6 ; calculate 2^^res
|
||
MOVE.L D6,D5 ; save here for boundary setting
|
||
ADDQ #2,D6 ; increase by 2 for the boundary
|
||
MOVE.L D6,D0 ; get it in a working register
|
||
MULU.W D6,D0 ; square it
|
||
MULU.W D6,D0 ; cube it
|
||
ADD.L D0,D0 ; table size -> words
|
||
MOVE.L D0,TblSize(A6) ; save size of table
|
||
|
||
bsr NewHandleTempSysApp ;search everywhere for some memory <28Feb90 KON>
|
||
bne MakeIErr ;failed! <28Feb90 KON>
|
||
;
|
||
; Got memory, check which heap it's in
|
||
;
|
||
tst.w d1 ;d1=0 -> memory in temp heap <28Feb90 KON>
|
||
bne.s @notTemp2 ; <28Feb90 KON>
|
||
bset #ITableInTempBit, isTmpHandle(a6) ;Main ITable is in temp memory <28Feb90 KON>
|
||
@notTemp2
|
||
|
||
MOVE.L A0,TblH(A6) ; save temporary table
|
||
MOVE.L (A0),A0 ; dereference the handle
|
||
MOVE.L A0,A3 ; set up the table base ptr
|
||
|
||
; and mark the boundaries of the cube. (thanks, Ernie)
|
||
|
||
Boundary
|
||
|
||
MOVE.L #((Bound)++(Bound<<16)),D1 ; get BOUND.LONG <C666/22Jan87> DAF
|
||
MOVE.L #((UNDEF)++(UNDEF<<16)),D0 ; GET UNDEF.LONG <C666/22Jan87> DAF
|
||
|
||
; DO TOP EXCEPT ONE ROW
|
||
|
||
MOVE D6,D4 ;GET WIDTH OF TOP
|
||
MULU D6,D4 ;GET AREA OF TOP
|
||
SUB D6,D4 ;BACK UP ONE ROW
|
||
SUBQ #1,D4 ;MAKE 0 BASED
|
||
LSR #1,D4 ;CONVERT TO LONGS (moved conversion!!)
|
||
|
||
CLRTOP MOVE.L D1,(A0)+ ;SET TOP TO BOUND
|
||
DBRA D4,CLRTOP ;=>UNTIL DONE
|
||
|
||
; FOR EACH MIDDLE SLAB, SET 2 ROWS TO BOUND
|
||
; THEN ONE LONG OF BOUND FOLLOWED BY WIDTH/2 LONGS OF UNDEF
|
||
|
||
SUB.L #2,A0 ;SO RIGHT/LEFT EDGES IN SAME LONG
|
||
|
||
MOVE D5,D4 ;GET NUMBER OF MIDDLE SLABS TO DO
|
||
SUBQ #1,D4 ;MAKE 0 BASED
|
||
|
||
CLRSLAB
|
||
MOVE.L D6,D3 ;DO 2 BOUND ROWS
|
||
SUBQ #1,D3 ; and adjust counter
|
||
TWOROWS MOVE.L D1,(A0)+ ;SET TO BOUND
|
||
DBRA D3,TWOROWS ;=>UNTIL DONE
|
||
|
||
MOVE.L D5,D2 ; get the number of rows in a layer
|
||
SUBQ #1,D2 ; convert to counter
|
||
ClrLayer
|
||
MOVE.L D1,(A0)+ ;PREVIOUS RIGHT, NEXT LEFT = BOUND
|
||
|
||
MOVE D5,D3 ;INNER ROW = UNDEF
|
||
LSR #1,D3 ; convert to long
|
||
SUBQ #1,D3 ; make this zero based, too
|
||
CLRROW MOVE.L D0,(A0)+ ;SET TO UNDEF
|
||
DBRA D3,CLRROW ;=>UNTIL DONE
|
||
|
||
DBRA D2,ClrLayer ;do each row of a layer
|
||
|
||
DBRA D4,CLRSLAB ;=>DO NEXT SLAB
|
||
|
||
; DO BOTTOM PLUS ONE ROW PLUS ONE WORD
|
||
|
||
MOVE D1,(A0)+ ;DO THE EXTRA WORD
|
||
|
||
MOVE D6,D4 ;GET WIDTH OF BOTTOM
|
||
MULU D6,D4 ;GET AREA OF BOTTOM
|
||
ADD.L D6,D4 ;ADD ONE ROW
|
||
SUBQ #1,D4 ;adjust for counter
|
||
LSR #1,D4 ;CONVERT TO LONGS (moved conversion!!)
|
||
|
||
CLRBOT MOVE.L D1,(A0)+ ;SET BOTTOM TO BOUND
|
||
DBRA D4,CLRBOT ;=>UNTIL DONE
|
||
|
||
|
||
; Time to queue the seed colors. First, make some lookup tables for the
|
||
; rgb components. This is necessary, since the "big" cube is (2^^n)+2
|
||
; in size, and the 3 indices can't be shifted and ORed together. These
|
||
; lookup tables are word sized, and looked up with a byte index. Each
|
||
; entry is repeated 2^^(8-res) times, which saves truncating the values.
|
||
; Since these tables are fairly small, and the queue is large, we build
|
||
; them at the end of the queue's memory space.
|
||
|
||
Seed
|
||
|
||
; first, calculate the inner and outer loop counts
|
||
|
||
MOVE.L D6,D4 ; calculate 2^^res (outer loop count)
|
||
SUBQ #3,D4 ; and turn it into a counter
|
||
|
||
MOVE.L #8,D3 ; compute 2^^(8-res) (inner loop count)
|
||
SUB res(A6),D3 ; get 8-res
|
||
MOVEQ #1,D5 ; prime for a power of two calc
|
||
LSL D3,D5 ; and get power of 2 in D5
|
||
SUBQ #1,D5 ; and turn it into a counter
|
||
|
||
; next, calculate increments and starting values
|
||
|
||
MOVE.L D6,D7 ; copy cube edge size to D7
|
||
MULU D6,D7 ; square it (size^^2 is increment for red)
|
||
|
||
MOVE.L D7,D0 ; init red value to include
|
||
ADD.L D6,D0 ; offset to (1,1,1) of the big cube
|
||
ADDQ #1,D0 ;
|
||
MOVEQ #0,D1 ; init green value
|
||
MOVEQ #0,D2 ; init blue value
|
||
|
||
; now figure out where the table starts. It's easy since the table is a
|
||
; constant size = 256 * 4 words = 1024 words = $800 bytes
|
||
|
||
MOVE.L A5,A0 ; copy the queue end addr
|
||
SUB.L #$800,A0 ; table starts here
|
||
MOVE.L A0,A2 ; remember it here
|
||
|
||
; OK, let's get to it! To make lookup easy, we multiplex the three tables
|
||
; together so it looks like RGBxRGBxRGBx. The "x" value lets us get to
|
||
; these entries using SCALE*8
|
||
|
||
@1
|
||
MOVE.L D5,D3 ; set up inner loop counter
|
||
@2
|
||
MOVE.W D0,(A0)+ ; write red
|
||
MOVE.W D1,(A0)+ ; write green
|
||
MOVE.W D2,(A0)+ ; write blue
|
||
ADDQ #2,A0 ; skip a word
|
||
|
||
DBRA D3,@2 ; for some number of times
|
||
|
||
ADD.W D7,D0 ; add size^^2 to red value
|
||
ADD.W D6,D1 ; add size to green value
|
||
ADD.W #1,D2 ; add one to blue value
|
||
|
||
DBRA D4,@1
|
||
|
||
;
|
||
; Queue the seed colors, marking their positional value in the color
|
||
; table in the big cube (don't use the colorSpec.index field!!)
|
||
;
|
||
|
||
MOVE.L QStart(A6),A4 ; initialize the queue insertion point to the beginning
|
||
ADDQ #2,A4 ; bump the start by a little
|
||
MOVE.L ([ITabH,A6]),A1 ; get a pointer to the colorTable
|
||
ADD.L InfoOffset(A6),A1 ; bump the pointer past the big table to the info stuff
|
||
CLR.W ITabHidden(A1) ; no hidden entries yet
|
||
CLR.W ITabReserved(A1) ; no extra fields yet
|
||
CLR.W ITabFlags(A1) ; not a gray ITab <BAL 16Mar89>
|
||
|
||
;
|
||
; Black and white's index values have special significance to QuickDraw in old grafPorts.
|
||
; By default, they are the first and last colors in the colortable. We queue them
|
||
; first so that they will never be overridden by identical colors in the interior of the
|
||
; colorTable. If B&W are not in their normal positions, old grafports will look funny
|
||
; anyway, so we don't need to check. D5 has the colorTable index to queue.
|
||
; <C751/03Feb87> DAF - Queuing order changed (search for *&*& to see end of change)
|
||
|
||
MOVE.L ([CTabH,A6]),A0 ; get a pointer to the colorTable
|
||
|
||
MOVEQ #0,D5 ; the first element is normally white (clr top half of D5, too)
|
||
BSR.S QUtil ; queue it
|
||
|
||
MOVE.W CTSize(A0),D5 ; the last element is normally black
|
||
BSR.S QUtil ; queue it
|
||
|
||
;
|
||
; order doesn't matter for the remaining colors. clut=8 has best results if we seed
|
||
; moving forward so let's do it that way.
|
||
;
|
||
|
||
MOVE.L D5,D4 ; copy total # of color (and cleared hi word)
|
||
SUBQ #2,D4 ; this is the number of colors remaining
|
||
BLE.S QVille ; if zero or negative, all done
|
||
MOVEQ #1,D5 ; start at color #1 (zero based)
|
||
@TheRestOfUs ; a temporary label for the rest of us
|
||
BSR.S QUtil ; queue it
|
||
ADDQ #1,D5 ; advance to next
|
||
DBRA D4,@TheRestOfUs ; and loop til done
|
||
BRA.S QVille ; and continue
|
||
|
||
;
|
||
; here's an inline queuing utility. This allows us to queue in any order, but particularily
|
||
; we can try to queue black and white first, to make sure that they are in the inverse
|
||
; table even though, by default they are at opposite ends of the colorTable. It's inline
|
||
; so it can be a short branch around it.
|
||
;
|
||
|
||
QUtil
|
||
BTST #ReserveBit,CTTable+value(A0,D5*8) ; is this color reserved? <C695/26Jan87> DAF
|
||
BNE.S @5 ; if so, don't queue <C695/26Jan87> DAF
|
||
MOVEQ #0,D0 ; clear the index register
|
||
MOVEQ #0,D1 ; init the lookup register
|
||
MOVE.B CTTable+rgb+red(A0,D5*8),D0 ; get the HI BYTE of red value
|
||
MOVE.W 0(A2,D0*8),D1 ; get the adjusted red value
|
||
MOVE.B CTTable+rgb+green(A0,D5*8),D0 ; get the HI BYTE of green value
|
||
ADD.W 2(A2,D0*8),D1 ; add the adjusted green value
|
||
MOVE.B CTTable+rgb+blue(A0,D5*8),D0 ; get the HI BYTE of blue value
|
||
ADD.W 4(A2,D0*8),D1 ; add the adjusted blue value
|
||
|
||
MOVE.W (A3,D1.L*2),D2 ; fetch the current value
|
||
BMI.B @4 ; if Undef (<0) then just use it
|
||
MOVE.B ITabInfo(A1,D2),ITabInfo(A1,D5) ; current.link := old.link
|
||
MOVE.B D5,ITabInfo(A1,D2) ; old.link := current
|
||
ADDQ.W #1,ITabHidden(A1) ; bump the number of hidden entries
|
||
BRA.S @5 ; branch to end of loop <C751/03Jan87> DAF
|
||
|
||
@4 MOVE.B D5,ITabInfo(A1,D5) ; make it self-referential
|
||
MOVE.W D5,(A3,D1.L*2) ; put the color in the cube
|
||
QUEUE D1,#0 ; queue the displacement
|
||
@5 ; <C695/26Jan87> DAF
|
||
RTS ; and return
|
||
|
||
;*&*& end of <C751/03Feb87> DAF
|
||
|
||
;
|
||
; Now it's time to propagate the seed values throughout the
|
||
; cube. The procedure is fairly straightforward- dequeue an element
|
||
; from the queue, then mark and queue its six neighbors until the
|
||
; cube is full. D6 still has the cube edge size (green delta),
|
||
; and D7 still has the size of a plane (red delta).
|
||
;
|
||
|
||
QVille
|
||
|
||
MOVE.L QStart(A6),A1 ; set the removal ptr to the 1st valid entry
|
||
ADDQ.L #2,A1 ; bump the end up to match the first entry
|
||
|
||
MOVEQ #1,D5 ; set up the blue delta
|
||
BRA @7 ; jump to end of loop (save 1 inst)
|
||
@1
|
||
LEA (A3,D1.L*2),A0 ; get the address of the queued element
|
||
|
||
MOVE.W (A0),D4 ; get the color value in this position (note that hi bit is set {that's good!})
|
||
|
||
BTST #7,(A0,D5.L*2) ; check the next blue
|
||
BEQ.S @2 ; if nonzero, then skip it
|
||
MOVE.W D4,(A0,D5.L*2) ; mark it as taken
|
||
QUEUE D1,D5 ; and queue the index
|
||
@2
|
||
NEG.L D5
|
||
BTST #7,(A0,D5.L*2) ; check the alternate blue
|
||
BEQ.S @3 ; if nonzero, then skip it
|
||
MOVE.W D4,(A0,D5.L*2) ; mark it as taken
|
||
QUEUE D1,D5 ; and queue the index
|
||
@3
|
||
BTST #7,(A0,D6.L*2) ; check the next green
|
||
BEQ.S @4 ; if nonzero, then skip it
|
||
MOVE.W D4,(A0,D6.L*2) ; mark it as taken
|
||
QUEUE D1,D6 ; and queue the index
|
||
@4
|
||
NEG.L D6
|
||
BTST #7,(A0,D6.L*2) ; check the alternate green
|
||
BEQ.S @5 ; if nonzero, then skip it
|
||
MOVE.W D4,(A0,D6.L*2) ; mark it as taken
|
||
QUEUE D1,D6 ; and queue the index
|
||
@5
|
||
BTST #7,(A0,D7.L*2) ; check the next red
|
||
BEQ.S @6 ; if nonzero, then skip it
|
||
MOVE.W D4,(A0,D7.L*2) ; mark it as taken
|
||
QUEUE D1,D7 ; and queue the index
|
||
@6
|
||
NEG.L D7
|
||
BTST #7,(A0,D7.L*2) ; check the alternate red
|
||
BEQ.S @7 ; if neg, then skip it
|
||
MOVE.W D4,(A0,D7.L*2) ; mark it as taken
|
||
QUEUE D1,D7 ; and queue the index
|
||
|
||
MOVEQ #0,D1 ; clear the hi half of the offset register
|
||
|
||
@7 DEQUEUE D1 ; pull a queue element
|
||
BNE @1 ; if the new one is zero, then done (0,0,0 is a boundary and never queued)
|
||
|
||
;
|
||
; the iLUT is now built. Compress it down to a byte table and resize the handle
|
||
;
|
||
|
||
Collapse
|
||
|
||
MOVE.L ITabH(A6),A0 ; get the ITable handle
|
||
MOVE.L (A0),A0 ; get pointer to ITable
|
||
MOVE.L ([CTabH,A6]),A2 ; get a pointer to the colortable <C239> DAF
|
||
MOVE.L CTSeed(A2),(A0)+ ; get the color table's seed value (itabSeed)
|
||
MOVE RES(A6),(A0)+ ; write out resolution (itabRes)
|
||
MOVE.L TblSize(A6),D0 ; get the cube size
|
||
LSR.L #1,D0 ; divide by 2 to get entry count in words
|
||
SUBQ #1,D0 ; and convert to counter for DBRA
|
||
MOVE.L TblH(A6),A2 ; get the cube handle
|
||
MOVE.L (A2),A2 ; get the cube pointer
|
||
|
||
@1 MOVE.W (A2)+,D1 ; get an element of the expanded table
|
||
CMP.W #BOUND,D1 ; is it a boundary cell?
|
||
BEQ.S @2 ; if so, then skip it
|
||
MOVE.B D1,(A0)+ ; if not, then write byte in final table
|
||
@2 DBRA D0,@1 ; loop through entire cube
|
||
|
||
MOVE.L TblH(A6),A0 ; get the temporary handle
|
||
; from QDciPatchROM.a MakeITable patch <sm 6/9/92>stb
|
||
btst #ITableInTempBit, isTmpHandle(a6) ;is handle in temp memory <28Feb90 KON>
|
||
beq.s @notTmp ; no, use normal dispose <2.2> BAL
|
||
_DisposeTempBuffer ; bag it <2.2> BAL
|
||
bra.s @allGone ; continue <2.2> BAL
|
||
|
||
@notTmp _DisposHandle ; release it
|
||
@allGone
|
||
|
||
;
|
||
; dispose of the memory for the Queue
|
||
;
|
||
DisposeQ ; <24Apr87> DAF
|
||
MOVE.L QHandle(A6),A0 ; release the queue <28Feb90 KON>
|
||
btst #QInTempBit, isTmpHandle(a6) ;is Queue in temp memory <28Feb90 KON>
|
||
beq.s @QnotTmp ; no, use normal dispose <28Feb90 KON>
|
||
_DisposeTempBuffer ; bag it <28Feb90 KON>
|
||
bra.s @QallGone ; continue <28Feb90 KON>
|
||
|
||
@QnotTmp _DisposHandle ; release it <28Feb90 KON>
|
||
@QallGone ; <28Feb90 KON>
|
||
|
||
|
||
MITDone ; <C695/26Jan87> DAF
|
||
; MOVE.L SvZone(A6),theZone ; always restore the zone (needed for error exits) <BAL>
|
||
MOVEM.L (SP)+,A2-A5/D3-D7 ; restore registers
|
||
UNLK A6 ; bag the stack frame
|
||
|
||
RTD #ParamSize ; flush parameters and return home <C733/02Feb87> DAF
|
||
|
||
MakeIErr ; <24Apr87> DAF
|
||
MOVE.W #CTempMemErr,QDErr ; report a table allocation error
|
||
bra.s DisposeQ
|
||
MakeIErrLate
|
||
MOVE.W #CTempMemErr,QDErr ; report a table allocation error
|
||
BRA.S MITDone
|
||
|
||
|
||
;----------------- Subroutine to hunt for memory -----------------------------
|
||
; from QDciPatchROM.a <sm 6/9/92>stb
|
||
|
||
NewHandleTempSysApp
|
||
;
|
||
; Called with requested size in d0. Routine first tries to get memory first in
|
||
; multifinder temp memory, then sys heap, then app heap. If memory found in
|
||
; temp memory, d1 returns 0, otherwise d1 is 1.
|
||
;
|
||
; Returns with: d0 error, 0=noErr
|
||
; a0 handle if no error
|
||
|
||
;
|
||
; Try temp memory if multifinder exists
|
||
;
|
||
move.l d0, -(sp) ;save requested size
|
||
moveq #0, d1 ;assume temp memory
|
||
_NewTempHandle ;look for it in temp memory
|
||
cmp.l (sp),d0 ;is it the size we requested?
|
||
beq.s @GotMem ;yes, it's big enough
|
||
|
||
_DisposeTempBuffer ;A0 already has handle of wrong size
|
||
;
|
||
; Try sys memory
|
||
;
|
||
@noMF
|
||
moveq #1, d1 ;not temp memory
|
||
move.l (sp),d0
|
||
_NewHandle ,sys
|
||
beq.s @GotMem
|
||
;
|
||
; Try app memory if zone different from system zone
|
||
;
|
||
move.l theZone,d0
|
||
cmp.l sysZone, d0 ;have we already tried this zone?
|
||
beq.s @Memoryerr ;don't try it again
|
||
|
||
move.l (sp),d0
|
||
_NewHandle
|
||
bne.s @MemoryErr ;couldn't find the memory anywhere
|
||
|
||
@GotMem
|
||
moveq #0,d0 ;signal noErr
|
||
@MemoryErr
|
||
addq #4,sp ;remove requested memory size
|
||
tst.w d0 ;set condition codes
|
||
rts
|
||
|
||
MakeGrayITab
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; MakeGrayITab
|
||
;
|
||
; At his point we know that all the clut entries are grays.
|
||
;
|
||
; First allocate a word-sized luminosity table on the stack and fill
|
||
; it with the appropriate index for each level by a seed fill method.
|
||
; Then compact the luminosity table into the ITInfoTable at the end of the ITab.
|
||
;
|
||
; Finally fill the ITab out with the appropriate index for each luminosity
|
||
; mapped position.
|
||
;
|
||
;PARAMSIZE EQU 10 ; total bytes of params
|
||
;CTabH EQU PARAMSIZE+8-4 ; Color table handle
|
||
;ITabH EQU CTabH-4 ; ITable handle
|
||
;RES EQU ITabH-2 ; entry size
|
||
;
|
||
;QStart EQU -4 ; pointer to the queue
|
||
;SvZone EQU QStart-4 ; save the current zone
|
||
;TblH EQU SvZone-4 ; copy of our temp ITable
|
||
;TblSize EQU TblH-4 ; size of our temp ITable
|
||
;InfoOffset EQU TblSize-4 ; offset to ITInfoTable from ITabH
|
||
;VARSIZE EQU InfoOffset
|
||
|
||
|
||
; Allocate and initialize table on stack
|
||
moveq #-1,d0 ; initializer for table
|
||
moveq #63,d1 ; # of double longs-1 in table
|
||
@1 move.l d0,-(sp) ; init 2 entries
|
||
move.l d0,-(sp) ; init 2 entries
|
||
dbra d1,@1
|
||
|
||
; Seed table with clut entries
|
||
|
||
clr.w 510(sp) ; seed white to guarantee last entry
|
||
move.w #255,(sp) ; seed black to guarantee 1st entry
|
||
|
||
move.l CTabH(a6),a0 ;
|
||
move.l (a0),a0 ; point at CLUT
|
||
move.w ctSize(a0),d0 ; get # entries -1
|
||
|
||
moveq #0,d2 ; clear out high end of word
|
||
@nxtEntry
|
||
move.w d0,d1 ; assume entry = index
|
||
btst #ReserveBit,ctTable+value(a0,d0*8)
|
||
bne.s @skip ; ignore reserved entries
|
||
; tst.w TransIndex(a0) ; look for flag in transIndex ASSUME DEVICE CLUT
|
||
; bmi.s @UseIndex ; => flag set, use index <BAL 29Mar89>
|
||
; move.w ctTable+value(a0,d0*8),d1 ; get value of current entry FUNG'S A HOSER
|
||
@UseIndex
|
||
move.b ctTable+rgb+red(a0,d0*8),d2 ; get luminance=red
|
||
move.w d1,(sp,d2*2) ; put pixel value in luminace table
|
||
@skip dbra d0,@nxtEntry ; => repeat until done
|
||
|
||
|
||
; Repeatedly smear right and then left one position until no changes in table
|
||
|
||
move.l a7,a1 ;
|
||
add.w #512,a1 ; set up limit pointer
|
||
@smear
|
||
moveq #0,d1 ; clear changed flag
|
||
lea 2(a7),a0 ; point at second entry
|
||
|
||
@right cmp.l a0,a1 ; reached end of table yet?
|
||
ble.s @end
|
||
tst.w (a0)+ ; is this entry occupied?
|
||
bpl.s @right ; yes, keep going
|
||
move.w -4(a0),-2(a0) ; no, smear right
|
||
addq #2,a0 ; don't smear more than one position
|
||
st d1 ; set changed flag
|
||
bra.s @right
|
||
|
||
@end subq #2,a0 ; stay inside last entry
|
||
@left cmp.l a0,a7 ; reached beginning of table yet?
|
||
bge.s @doneSmear
|
||
tst.w -(a0) ; is this entry occupied?
|
||
bpl.s @left ; yes, keep going
|
||
move.w 2(a0),(a0) ; no, smear left
|
||
subq #2,a0 ; don't smear more than one position
|
||
st d1 ; set changed flag
|
||
bra.s @left
|
||
|
||
@doneSmear
|
||
tst d1 ; were there any changes?
|
||
bne.s @smear ; yes, smear some more
|
||
|
||
; Now compress the table into the ITInfoTable and discard the stack version.
|
||
|
||
move.l ITabH(a6),a1 ;
|
||
move.l (a1),a1 ;
|
||
|
||
move.l ([CTabH,a6]),a2 ; get a pointer to the colortable
|
||
move.l CTSeed(a2),iTabSeed(a1) ; get the color table's seed value
|
||
move RES(a6),iTabRes(a1) ; write out resolution
|
||
|
||
add.l InfoOffset(a6),a1 ; point at ITInfoTable
|
||
bset #15,iTabFlags(a1) ; set grayITab flag
|
||
move.w #255,d0 ; get table size
|
||
lea ITabLuma(a1),a3 ; point at luma table
|
||
|
||
@copy move.b 1(sp,d0*2),d1 ; get index
|
||
move.b d1,ITabInfo(a1,d0) ; copy into ITInfoTable
|
||
move.b ctTable+rgb+red(a2,d1*8),(a3,d0) ; get actual luminance=red for dither error table
|
||
dbra d0,@copy
|
||
|
||
add.w #512,sp ; discard temp table
|
||
|
||
; Now fill out the ITab with luminance mapped index values at each location.
|
||
|
||
|
||
MOVE.L ([ITabH,a6]),A0 ; get the iTable's master pointer
|
||
MOVEQ #1,D0 ; prime the register again <BAL 16Mar89>
|
||
MOVE ITabRes(A0),D2 ; get the inverse table resolution (and Bit-field width)
|
||
LSL.L D2,D0 ; calculate 2^res
|
||
subq #1,d0 ; make it zero based for dbra
|
||
LEA ITTable(A0),A0 ; point us at the ITab data
|
||
lea ITabInfo(a1),a1 ; bump past header
|
||
|
||
move #2*256,d4 ; start with max blue contribution
|
||
lsr.w d2,d4 ; divide by # of steps
|
||
move #9*256,d5 ; start with max green contribution
|
||
lsr.w d2,d5 ; divide by # of steps
|
||
sub #2*256,d5 ; adjust for reverse blue bump
|
||
move #5*256,d6 ; start with max red contribution
|
||
lsr.w d2,d6 ; divide by # of steps
|
||
sub #9*256,d6 ; adjust for reverse green bump
|
||
|
||
;-------------------------------------------------------
|
||
; a0 = ITTable d0 = 2^iTabRes
|
||
; a1 = ITabInfo d1 = red looper
|
||
; a2 = cur luma d2 = green looper
|
||
; a3 = d3 = blue looper
|
||
; a4 = d4 = blue bump
|
||
; a5 = d5 = green bump - max blue
|
||
; a6 = locals d6 = red bump - max green
|
||
; a7 = d7 = scratch
|
||
;-------------------------------------------------------
|
||
sub.l a2,a2 ; init composite luminance
|
||
move.w d0,d1 ; init red position
|
||
@red move.w d0,d2 ; init green position
|
||
@green move.w d0,d3 ; init blue position
|
||
@blue move.w a2,d7 ; make a copy
|
||
lsr.w #4,d7 ; normalize luminance
|
||
move.b (a1,d7),(a0)+ ; store index in table
|
||
add d4,a2 ; bump in blue
|
||
dbra d3,@blue
|
||
add d5,a2 ; bump back to zero blue coordinate and increment green
|
||
dbra d2,@green
|
||
add d6,a2 ; bump back to zero green coordinate
|
||
dbra d1,@red
|
||
|
||
; bra MITDone ; all done
|
||
rts
|
||
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; function ITabMatch ( myColor : RGBColor; var MatchPos : longint ) : boolean;
|
||
;
|
||
; This procedure takes an RGBColor and finds the best match
|
||
; to the .rgb field by lookup in the inverse table. The resultant
|
||
; index value is extended to a long and returned as the result.
|
||
; As the default routine, it does not look at the CDID field and
|
||
; always returns a result. It uses the linked list at the end of the
|
||
; ILUT to find and return "hidden" colors, based on a simple best fit
|
||
; calculation.
|
||
;
|
||
|
||
ITabMatch PROC EXPORT
|
||
|
||
PARAMSIZE EQU 10 ; total bytes of params
|
||
Result EQU PARAMSIZE+8-2
|
||
MyColor EQU Result-4
|
||
MatchPos EQU MyColor-4
|
||
|
||
Best EQU -2 ; keeps track of our index during hidden searches
|
||
BestVal EQU Best-2 ; keeps track of the best value while searching
|
||
EndLink EQU BestVal-2 ; the self-referential link that signals stop
|
||
ITabInfoPtr EQU EndLink-4 ; pointer to hidden colors, etc
|
||
VARSIZE EQU ITabInfoPtr
|
||
|
||
|
||
LINK A6,#VARSIZE ; set up a stack frame
|
||
MOVE.L A2,-(SP) ; save a register <C835/20Feb87> DAF
|
||
CLR.B Result(A6) ; assume boolean false
|
||
|
||
MOVE.L ([theGDevice]),A2 ; get a pointer to the current device
|
||
MOVE.L ([GDPMap,A2]),A1 ; get pixMap's handle
|
||
MOVE.L PMTable(A1),A0 ; get the device colorTable's handle
|
||
MOVE.L ([A0],CTSeed),D1 ; get a pointer to the device colortable
|
||
MOVE.L ([GDITable,A2]),D0 ; get the Itable's master pointer
|
||
CMP.L (ITabSeed,ZA0,D0.L),D1 ; has the colortable changed?
|
||
BEQ.S @1 ; if equal, then the iTable is OK
|
||
|
||
; if table is not up to date, build a new one
|
||
|
||
MOVE.L A0,-(SP) ; push theGDevice's color table handle
|
||
MOVE.L GDITable(A2),-(SP) ; push theGDevice's current iTabHandle
|
||
MOVE.W GDResPref(A2),-(SP) ; push the preferred iTableResolution
|
||
_MakeITable ; make a new table
|
||
; TST.W QDErr ; was this successful? <2.2> BAL
|
||
; BNE MtchEnd ; nope, so quit <2.2> BAL
|
||
MOVE.L ([theGDevice]),A2 ; redereference in case it moved <BAL 31Mar89>
|
||
MOVE.L ([GDITable,A2]),D0 ; get the iTable's master pointer
|
||
|
||
@1 MOVE.L D0,A0 ; and get a pointer to the ITab
|
||
MOVEQ #1,D0 ; prime the register again <BAL 16Mar89>
|
||
MOVE ITabRes(A0),D2 ; get the inverse table resolution (and Bit-field width)
|
||
LSL.L D2,D0 ; calculate 2^^res
|
||
LSL.L D2,D0 ; square it
|
||
LSL.L D2,D0 ; cube it
|
||
LEA ITTable(A0,D0.L),A1 ; point us at the ITabInfo
|
||
move.l a1,ITabInfoPtr(a6) ; save for later
|
||
tst.w iTabFlags(a1) ; is this a grayITab? <BAL 16Mar89>
|
||
bpl.s @notGray
|
||
|
||
; Now we know that all matchable clut entries are grays so simply compute luminance
|
||
; of input RBG and return index from 256 entry luminance table at end of the grayITab.
|
||
|
||
|
||
move.l myColor(a6),a0 ; get a pointer to the RGBColor
|
||
lea red(a0),a0 ; point at red cmp
|
||
moveq #0,d0 ; clear out high end
|
||
moveq #0,d1 ; clear out high end
|
||
moveq #0,d2 ; clear out high end
|
||
move.w (a0)+,d0 ; get the red component
|
||
move.w (a0)+,d1 ; get the green component
|
||
move.w (a0),d2 ; get the blue component
|
||
|
||
; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2
|
||
|
||
move.l d1,a0 ; copy green
|
||
add.l d0,d1
|
||
lsr.l #1,d1
|
||
add.l d2,d1
|
||
lsr.l #1,d1
|
||
add.l d0,d1
|
||
lsr.l #1,d1
|
||
add.l a0,d1
|
||
lsr.l #1,d1
|
||
lsr.l #8,d1 ; make into byte value
|
||
|
||
move.b ITabInfo(A1,D1),D1 ; pick up index for this luminance
|
||
bra FoundIt ; => D1 has the answer
|
||
|
||
|
||
|
||
@notGray
|
||
MOVE ITabRes(A0),D2 ; get the inverse table resolution (and Bit-field width)
|
||
MOVE.L myColor(A6),A1 ; get a pointer to the RGBColor
|
||
BFEXTU red(A1){0:D2},D0 ; get the red component (BFEXTU zero extends)
|
||
LSL.L D2,D0 ; and shift it over res bits
|
||
BFEXTU green(A1){0:D2},D1 ; get the green component
|
||
OR.L D1,D0 ; put them together
|
||
LSL.L D2,D0 ; shift over again
|
||
BFEXTU blue(A1){0:D2},D1 ; get the blue component
|
||
OR.L D1,D0 ; and here's the completed index
|
||
|
||
; BFEXTU clears high 3 bytes of D1
|
||
|
||
MOVE.B ITTable(A0,D0),D1 ; get the index value
|
||
|
||
; Now we have the index, but we may not have the best match it can offer. See if
|
||
; it is self referential within the ITabInfo table, in which case it is probably the best
|
||
|
||
move.l ITabInfoPtr(a6),a1 ; point us at the ITabInfo <BAL 16Mar89>
|
||
CMP.B ITabInfo(A1,D1),D1 ; is this entry self referential?
|
||
BEQ.S FoundIt ; => D1 has the answer
|
||
|
||
; Where we keep some stuff:
|
||
; A0 - pointer to target RGBColor
|
||
; A1 - pointer to ITabInfo
|
||
; A2 - pointer to color table of current device
|
||
; D0 - calculates and holds the "distance"
|
||
; D1 - best index found
|
||
; D2 - used to calculate difference
|
||
|
||
MOVE.L myColor(A6),A0 ; get a pointer to the RGBColor
|
||
|
||
MOVE.L ([theGDevice]),A2 ; get the current device pointer
|
||
MOVE.L ([GDPMap,A2]),A2 ; get the device pixelmap pointer
|
||
MOVE.L ([pmTable,A2]),A2 ; point to the color table
|
||
|
||
MOVE.W D1,Best(A6) ; save current index - high byte is 0
|
||
MOVE.W D1,EndLink(A6) ; terminate when Current.Link = EndLink
|
||
MOVE.W #$7FFF,BestVal(A6) ; BestVal := $7FFF
|
||
|
||
; Okay, we have to look through the hidden values until we find the best match. This is a
|
||
; crude and simple search - we estimate the "distance" between our target and a hidden value
|
||
; based upon max(abs(∆Red),max(abs(∆Blue),abs(∆Green))). We select the index which has the minimum
|
||
; "distance", stopping early if we find an exact match.
|
||
|
||
Repeatr MOVE.W CTTable+rgb+red(A2,D1.W*8),D0 ; get red value of current index
|
||
SUB.W Red(A0),D0 ; subtract target red
|
||
BPL.S @1 ; make it positive
|
||
NEG D0 ; like so
|
||
@1 MOVE.W CTTable+rgb+green(A2,D1.W*8),D2 ; get green value of current index
|
||
SUB.W Green(A0),D2 ; subtract target green
|
||
BPL.S @2 ; make it positive
|
||
NEG D2 ; like so
|
||
@2 CMP.W D2,D0 ; select D0 := max(D2,D0)
|
||
BGE.S @3
|
||
MOVE.W D2,D0
|
||
@3 MOVE.W CTTable+rgb+blue(A2,D1.W*8),D2
|
||
SUB.W Blue(A0),D2
|
||
BPL.S @4
|
||
NEG D2
|
||
@4 CMP.W D2,D0
|
||
BGE.S @5
|
||
MOVE.W D2,D0
|
||
@5 TST.W D0 ; check result of our calculations
|
||
BEQ.S FoundIt ; D1 has the best match
|
||
|
||
CMP.W BestVal(A6),D0
|
||
BGE.S NotBest
|
||
|
||
; Set BestVal to the newly calculated match and update BestIndex
|
||
|
||
MOVE.W D0,BestVal(A6) ; copy new best value into holder
|
||
MOVE.W D1,Best(A6) ; copy current index into result
|
||
NotBest MOVE.B ITabInfo(A1,D1.W),D1 ; get the next link - high byte still 0
|
||
CMP.W EndLink(A6),D1 ; are we done?
|
||
BNE.S Repeatr
|
||
MOVE.W Best(A6),D1 ; grab the best match into D1
|
||
FoundIt MOVE.L MatchPos(A6),A0 ; get pointer to index result
|
||
EXT.L D1 ; make sure the upper word is clear
|
||
MOVE.L D1,(A0) ; write result
|
||
MOVE.B #1,Result(A6) ; and return boolean true
|
||
|
||
MtchEnd MOVE.L (SP)+,A2 ; restore register (was 2) <C835/20Feb87> DAF
|
||
UNLK A6 ; release stack frame
|
||
RTD #8 ; and go home
|
||
|
||
|
||
|
||
|
||
|
||
ColorThing2Index PROC EXPORT ; <BAL/dvb 23Feb89>
|
||
EXPORT Color2Index
|
||
;
|
||
;
|
||
; function ColorThing2Index ( myThing : ColorThing ) : longint;
|
||
;
|
||
; This procedure takes an RGB colorSpec-like thing and returns
|
||
; the appropriate pixel value for the current GDevice (despite how much I
|
||
; hate the concept of THEGDevice damn it!). But atleast we can share code.
|
||
;
|
||
|
||
; ColorThing format
|
||
|
||
colorSpace equ 0 ;[byte] 0=RGB, 1=palette index, 2=?
|
||
ctFiller equ colorSpace+1 ;[byte] reserved for clut compatibility
|
||
colorData equ ctFiller+1 ;actual color stuff, 0->48bit RGB, 1->16bit palette index
|
||
|
||
result EQU 12 ; longword result
|
||
myThing EQU 8 ; pointer to colorThing
|
||
retAddr EQU 4 ; return address
|
||
LongRes EQU -4 ; space for a longint return
|
||
FrameSize EQU LongRes ;
|
||
|
||
LINK A6,#FrameSize ;
|
||
|
||
clr.l -(sp) ; make room for result
|
||
move.l myThing(a6),a0 ; get thing ptr
|
||
move.w (a0)+,-(sp) ; push palette index
|
||
move.l a0,myThing(a6) ; set to RGB ptr for color2Index
|
||
moveq #0,d0 ; Entry2Index selector
|
||
; dc.w $aaa2 ; ask the brink
|
||
jsr ([$e00+(4*$2a2)]) ; ask the brink (faster)
|
||
move.l (sp)+,result(a6) ; get the answer
|
||
move.w qderr,d0 ; is it real?
|
||
bne.s c2iShare
|
||
UNLK A6 ; release stack frame
|
||
RTD #4 ; return and dealloc
|
||
|
||
;
|
||
; function Color2Index ( myColor : RGBColor ) : longint;
|
||
;
|
||
; This procedure takes an RGB color specification and finds it's best
|
||
; match using the search rule chain. The resultant index value is
|
||
; returned right-justified in the longword result. Note that direct
|
||
; mapping devices MUST have a searchProc.
|
||
;
|
||
|
||
Color2Index ;PROC EXPORT ; interface modified <C491/06Dec86> DAF
|
||
|
||
;result EQU 12 ; longword result <C601/07Jan87> DAF
|
||
MyColor EQU 8 ; pointer to rgbColor <C601/07Jan87> DAF
|
||
;retAddr EQU 4 ; return address <C601/07Jan87> DAF
|
||
;LongRes EQU -4 ; space for a longint return <C601/07Jan87> DAF
|
||
;FrameSize EQU LongRes ;
|
||
|
||
LINK A6,#FrameSize ; <C601/07Jan87> DAF
|
||
c2iShare
|
||
MOVE.L A2,-(SP) ; save a register <C491/06Dec86> DAF
|
||
; CLR.W QDErr ; clear the error register <1.9>
|
||
|
||
MOVE.L ([theGDevice]),A2 ; get a pointer to the device port
|
||
|
||
if 0 then
|
||
MOVE.L GDSearchProc(A2),D0 ; get the head of the search chain
|
||
|
||
@1
|
||
BEQ.S DefRule ; if NIL, then apply default rule
|
||
MOVE.L D0,A2 ; save the search element handle <C666/22Jan87> DAF
|
||
MOVE.L D0,A0 ; and set up for HLock <C666/22Jan87> DAF
|
||
_HLock ; lock the search element (so A2 will be valid after searchProc) <C666/22Jan87> DAF
|
||
SUBQ #2,SP ; make room for boolean result <C601/07Jan87> DAF
|
||
MOVE.L MyColor(A6),-(SP) ; push RGBColor pointer <C601/07Jan87> DAF
|
||
PEA LongRes(A6) ; push pointer to placeholder <C601/07Jan87> DAF
|
||
MOVE.L (A2),A0 ; get pointer to search element <C666/22Jan87> DAF
|
||
MOVE.L SrchProc(A0),A0 ; get the searchProc address <C666/22Jan87> DAF
|
||
JSR (A0) ; execute routine <C491/06Dec86> DAF
|
||
MOVE.L A2,A0 ; unlock the search element now <C666/22Jan87> DAF
|
||
_HUnlock ; <C666/22Jan87> DAF
|
||
TST.B (SP)+ ; test the boolean result <C601/07Jan87> DAF
|
||
BNE.S Found1 ; if result = TRUE then quit <C601/07Jan87> DAF
|
||
MOVE.L (A2),A0 ; get pointer to this search element again <C666/22Jan87> DAF
|
||
MOVE.L NxtSrch(A0),D0 ; get pointer to next <C666/22Jan87> DAF
|
||
BRA.S @1 ;
|
||
endif
|
||
|
||
;-----------Optimization <20AUG90 KON> Hopefully it still works--------------------------------
|
||
MOVE.L GDSearchProc(A2),a2 ; get the head of the search chain <20AUG90 KON>
|
||
NxtProc
|
||
MOVE.L A2,D0 ; To work register <20AUG90 KON>
|
||
beq.s DefRule ; no search proc, or end of list <20AUG90 KON>
|
||
MOVE.L (A2),A0 ; get pointer to search element <C666/22Jan87> DAF
|
||
move.l NxtSrch(a0),a2 ; get handle to next search element <20AUG90 KON>
|
||
;
|
||
; Call search proc
|
||
;
|
||
SUBQ #2,SP ; make room for boolean result <C601/07Jan87> DAF
|
||
MOVE.L MyColor(A6),-(SP) ; push RGBColor pointer <C601/07Jan87> DAF
|
||
PEA LongRes(A6) ; push pointer to placeholder <C601/07Jan87> DAF
|
||
MOVE.L SrchProc(A0),A0 ; get the searchProc address <C666/22Jan87> DAF
|
||
JSR (A0) ; execute routine <C491/06Dec86> DAF
|
||
TST.B (SP)+ ; test the boolean result <C601/07Jan87> DAF
|
||
beq.s NxtProc ; not found, try next search proc <20AUG90 KON>
|
||
;-----------END <20AUG90 KON> -----------------------------------------------------------------
|
||
|
||
Found1
|
||
MOVE.L LongRes(A6),D0 ; get the longword index <C601/07Jan87> DAF
|
||
MOVE.L D0,result(A6) ; return result <C491/06Dec86> DAF
|
||
MOVE.L (SP)+,A2 ; restore saved register <C491/06Dec86> DAF
|
||
UNLK A6 ; release stack frame <C601/07Jan87> DAF
|
||
RTD #4 ; return and dealloc
|
||
|
||
|
||
DefRule
|
||
MOVE.L ([theGDevice]),A0 ; get a pointer to the device port <C777/12Feb87> DAF
|
||
CMP.W #DirectType,GDType(A0) ; if it is direct, don't call ITabMatch <C777/12Feb87> DAF
|
||
BEQ.S @DirectPix ; calc direct pixel value <C777/12Feb87> DAF
|
||
CLR.B -(SP) ; make room for function result <C583/02Jan87> DAF
|
||
MOVE.L myColor(A6),-(SP) ; push RGBColor pointer
|
||
PEA LongRes(A6) ; push pointer to index placeholder <C583/02Jan87> DAF
|
||
_ITabMatch ; call the default routine
|
||
TST.B (SP)+ ; test the boolean result <C491/06Dec86> DAF
|
||
;BNE.S GetIt ; if OK result, get index <C583/02Jan87> DAF
|
||
bra.s GetIt ; just get index anyway
|
||
@DirectPix
|
||
MOVE.L ([GDPMap,A0]),A1 ; get the device pixelmap pointer
|
||
move.w cmpSize(a1),d1 ; get cmp size <rgb/06Jul88> BAL
|
||
MOVE.L myColor(A6),A0 ; point to the color spec <RGB/19May88> DAF
|
||
moveq #0,d0 ; clear a register <rgb/06Jul88> BAL
|
||
MOVE.B red(A0),D0 ; get the red channel <RGB/19May88> DAF
|
||
LSL.L d1,D0 ; shift over <RGB/19May88> DAF
|
||
MOVE.B green(A0),D0 ; get the green channel <RGB/19May88> DAF
|
||
LSL.L d1,D0 ; shift again <RGB/19May88> DAF
|
||
MOVE.B blue(A0),D0 ; get the blue channel <RGB/19May88> DAF
|
||
neg.w d1
|
||
addq.w #8,d1 ; shift needed to right justify pixel
|
||
ble.s @noShift ; needed for cmpSize=10
|
||
lsr.l d1,d0
|
||
@noShift
|
||
|
||
MOVE.L D0,LongRes(A6) ; just for now! <RGB/19May88> DAF
|
||
GetIt BRA.S Found1 ; and return <C583/02Jan87> DAF
|
||
|
||
|
||
;
|
||
; procedure Index2Color ( index : longint; VAR myColor : RGBColor );
|
||
;
|
||
; This procedure takes an index value and returns the RGB
|
||
; components of this element of theGDPort^^.GDPMap.pmTable.
|
||
;
|
||
; as seen in QDciPatchROM.a <sm 6/9/92>stb
|
||
|
||
Index2Color PROC EXPORT
|
||
|
||
MOVE.L 8(SP),D0 ; get the index <C491/06Dec86> DAF
|
||
MOVE.L 4(SP),A0 ; get pointer to result RGB <C491/06Dec86> DAF
|
||
MOVE.L ([theGDevice]),A1 ; get the current device pointer
|
||
MOVE.L ([GDPMap,A1]),A1 ; get the device pixelmap pointer
|
||
cmp #16,pixelType(a1) ; is it a direct device? <BAL 06Jul88>
|
||
beq.s I2CDirect ; yes, no CLUT <BAL 06Jul88>
|
||
|
||
MOVE.L ([pmTable,A1]),A1 ; point to the color table
|
||
; CLR.W QDErr ; clear the error register <1.9>
|
||
|
||
MOVE.W ctSize(A1),D1 ; get ctSize <C491/06Dec86> DAF
|
||
CMP.W D1,D0 ; is index in range? <C491/06Dec86> DAF
|
||
BGT.S I2CErr ; nope, so quit <C491/06Dec86> DAF
|
||
MOVE.W CTTable+rgb+red(A1,D0.L*8),red(A0) ; move red <C491/06Dec86> DAF
|
||
MOVE.L CTTable+rgb+green(A1,D0.L*8),green(A0) ; move green & blue <C491/06Dec86> DAF
|
||
I2CDone
|
||
RTD #8 ; and return
|
||
|
||
I2CErr
|
||
MOVE.W #cRangeErr,QDErr ; set error code
|
||
BRA.S I2CDone ;
|
||
|
||
I2CDirect ; Handle 24bit/pixel direct devices <BAL 06Jul88>
|
||
moveq #8,d1 ; get handy constant
|
||
sub.w cmpSize(a1),d1 ; shift needed to left justify cmp
|
||
beq.s I2C24 ; cmpsize is 8 so go fast
|
||
|
||
;enter with a 16-bit source pixel in d0
|
||
|
||
lsl.l #3,d0 ;left align blue in lo byte
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;get 5 bits of blue
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;make into 10 bits of blue
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;make into 15 bits of blue
|
||
move.b d0,d1
|
||
lsr.l #7,d1 ;get a word of blue
|
||
MOVE.w d1,blue(a0) ;store out in color spec
|
||
|
||
lsr.l #5,d0 ;left align green in lo byte
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;get 5 bits of green
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;make into 10 bits of green
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;make into 15 bits of green
|
||
move.b d0,d1
|
||
lsr.l #7,d1 ;get a word of green
|
||
MOVE.w d1,green(a0) ;store out in color spec
|
||
|
||
lsr.l #5,d0 ;left align red in lo byte
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;get 5 bits of red
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;make into 10 bits of red
|
||
move.b d0,d1
|
||
lsl.l #5,d1 ;make into 15 bits of red
|
||
move.b d0,d1
|
||
lsr.l #7,d1 ;get a word of red
|
||
MOVE.w d1,red(a0) ;store out in color spec
|
||
|
||
|
||
if 0 then
|
||
lsl.l d1,d0 ; put cmp at high end of byte
|
||
move.w cmpSize(a1),d1 ; get distance to next cmp
|
||
|
||
move.b d0,d2 ; make a copy
|
||
lsl.w d1,d2 ; preserve cmpSize bits in high byte
|
||
move.b d0,d2 ; replicate cmpSize bits
|
||
lsr.w d1,d2 ; make into a byte
|
||
|
||
move.b d2,blue(a0) ; set up high byte of blue result
|
||
move.b d2,blue+1(a0) ; set up low byte of blue result
|
||
|
||
move.w d0,d2 ; make a copy of cmpSize bits in high byte
|
||
lsr.l d1,d0 ; get next cmp in high end of lo byte
|
||
move.b d0,d2 ; replicate cmpSize bits
|
||
lsr.w d1,d2 ; make into a byte
|
||
|
||
move.b d2,green(a0) ; high green
|
||
move.b d2,green+1(a0) ; low green
|
||
|
||
move.w d0,d2 ; make a copy of cmpSize bits in high byte
|
||
lsr.l d1,d0 ; get next cmp in high end of lo byte
|
||
move.b d0,d2 ; replicate cmpSize bits
|
||
lsr.w d1,d2 ; make into a byte
|
||
|
||
move.b d2,red(a0) ; high red
|
||
move.b d2,red+1(a0) ; low red
|
||
endif
|
||
|
||
bra.s I2CDone
|
||
|
||
I2C24
|
||
move.b d0,blue(a0) ; set up high byte of blue result
|
||
move.b d0,blue+1(a0) ; set up low byte of blue result
|
||
lsr.w #8,d0 ; get green byte
|
||
move.b d0,green(a0) ; high green
|
||
move.b d0,green+1(a0) ; low green
|
||
swap d0 ; get red byte
|
||
move.b d0,red(a0) ; high red
|
||
move.b d0,red+1(a0) ; low red
|
||
bra.s I2CDone
|
||
|
||
;
|
||
; procedure InvertColor ( VAR myColor : RGBColor );
|
||
;
|
||
; This procedure takes an RGBColor, calculates its inverse using the current
|
||
; inverse rules, then updates the provided RGBColor. It only uses the
|
||
; compProc interface if the default is not called.
|
||
;
|
||
; has fix from QDciPatchROM.a where an offset was wrong because of a byte result <sm 6/9/92>stb
|
||
|
||
InvertColor PROC EXPORT
|
||
|
||
MOVE.L A2,-(SP) ; save a register <C601/07Jan87> DAF
|
||
MOVE.L ([theGDevice]),A2 ; get a pointer to the device port
|
||
MOVE.L GDCompProc(A2),D0 ; get the head of the complement chain
|
||
@1
|
||
BEQ.S DefComp ; if NIL, then apply default rule
|
||
MOVE.L D0,A2 ; save the pointer <C601/07Jan87> DAF
|
||
MOVE.L D0,A0 ; set up to lock this element <C666/22Jan87> DAF
|
||
_HLock ; lock it down so that A2 will be valid after the JSR <C666/22Jan87> DAF
|
||
CLR.B -(SP) ; room for a boolean result
|
||
MOVE.L 8+2(SP),-(SP) ; push the pointer to the color <26MAR90 KON>
|
||
MOVE.L (A0),A0 ; get the element pointer <C666/22Jan87> DAF
|
||
MOVE.L CompProc(A0),A0 ; get the complement proc ptr <C666/22Jan87> DAF
|
||
JSR (A0) ; execute routine
|
||
MOVE.L A2,A0 ; set up for HUnlock <C666/22Jan87> DAF
|
||
_HUnlock ; release the compElement <C666/22Jan87> DAF
|
||
TST.B (SP)+ ; test the result
|
||
BNE.S FoundComp ; if result = TRUE then quit
|
||
MOVE.L (A2),A0 ; get the compElement pointer again <C666/22Jan87> DAF
|
||
MOVE.L NxtComp(A0),D0 ; get pointer to next <C666/22Jan87> DAF
|
||
BRA.S @1 ;
|
||
|
||
FoundComp
|
||
MOVE.L (SP)+,A2 ; restore the register <C601/07Jan87> DAF
|
||
RTD #4 ; and go home
|
||
|
||
; the default procedure is VERY simple. It just gets the complement of each
|
||
; component. It always returns a sucessful result.
|
||
DefComp
|
||
MOVE.L 8(SP),A0 ; get pointer to RGBColor
|
||
|
||
NOT.W (A0)+ ; complement red
|
||
NOT.W (A0)+ ; complement green
|
||
NOT.W (A0) ; complement bleu, svp.
|
||
BRA.S FoundComp ; and it always works too.
|
||
|
||
|
||
;
|
||
; 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
|
||
;
|
||
|
||
RGBForeColor PROC EXPORT
|
||
EXPORT RGBBackColor,RGB2OLD
|
||
|
||
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.S DONE ; => and return
|
||
|
||
; Palette manager patch rolled in <6Jun87 EHB>
|
||
; Flag to the Palette Manager whether it a foreground or a background call happened
|
||
|
||
NEWPORT MOVE.L GrafVars(A0),D2 ; get the GrafVars handle <6Jun87 EHB>
|
||
BEQ.S NoPM ; =>no grafVars, continue <6Jun87 EHB>
|
||
MOVE.L D2,A1 ; else get GrafVars handle <6Jun87 EHB>
|
||
MOVE.L (A1),A1 ; point to GrafVars <6Jun87 EHB>
|
||
MOVE PmFlags(A1),D2 ; get flags <6Jun87 EHB>
|
||
CMP #FgColor,D0 ; is this a foreground call? <6Jun87 EHB>
|
||
BNE.S NotFg ; no => clear PmBkBit <6Jun87 EHB>
|
||
BCLR #PmFgBit,D2 ; clear the foreground flag bit <6Jun87 EHB>
|
||
BRA.S Common ; reunite it <6Jun87 EHB>
|
||
|
||
NotFg BCLR #PmBkBit,D2 ; clear the background flag bit <6Jun87 EHB>
|
||
Common MOVE D2,PmFlags(A1) ; save the flags to GrafVars <6Jun87 EHB>
|
||
MOVE.L 8(SP),A1 ; restore the pointer to the RGBColor <6Jun87 EHB>
|
||
|
||
NoPM 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 <C491/06Dec86> DAF
|
||
PEA 4(SP) ; push pointer to rgb <C491/06Dec86> DAF
|
||
_Color2Index ; convert it to an index
|
||
|
||
MOVE.L (SP)+,D0 ; get the index result <C491/06Dec86> DAF
|
||
ADDQ #6,SP ; get rid of the rgbColor <C491/06Dec86> DAF
|
||
|
||
DONE MOVE.L (SP)+,A0 ; get pointer to index field
|
||
MOVE.L D0,(A0) ; and set the index field
|
||
RTD #4 ; all done <C491/06Dec86> DAF
|
||
|
||
|
||
|
||
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
|
||
ADD.L D1,D1 ; get high bit
|
||
MOVE (A1)+,D1 ; get green
|
||
ADD.L D1,D1 ; get high bit
|
||
MOVE (A1)+,D1 ; get blue
|
||
ADD.L D1,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.
|
||
;
|
||
|
||
RGBBackColor
|
||
|
||
MOVEQ #BKCOLOR,D0 ; get offset to the index field
|
||
MOVEQ #RGBBkColor,D1 ; get offset to RGB field
|
||
BRA.S SHARE ; => and use common code
|
||
|
||
;
|
||
; PROCEDURE GetForeColor (VAR Color: RGBColor);
|
||
;
|
||
; Return the RGB components of the current foreground color
|
||
; Works for old and new ports.
|
||
|
||
|
||
GetForeColor PROC EXPORT
|
||
EXPORT GetBackColor
|
||
|
||
MOVEQ #FGCOLOR,D0 ; get offset to the 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
|
||
TST PORTBITS+ROWBYTES(A0) ; is it a new port?
|
||
BPL.S GETOLD ; => no, set using planar values
|
||
|
||
MOVE.L red(A0,D1),red(A1) ; copy red and green components from the port
|
||
MOVE.W blue(A0,D1),blue(A1) ; and blue too
|
||
|
||
DONE MOVE.L (SP)+,A0 ; get the return address
|
||
ADDQ #4,SP ; get rid of the parameter
|
||
JMP (A0) ; and return
|
||
|
||
; USE CMYB BITS IN COLOR TO DERIVE PROPER RGB COMPONENTS
|
||
|
||
GETOLD MOVE.L (A0,D0),D0 ; get planar color from port
|
||
LSR #1,D0 ; CHECK FOR WHITE (I CMYB rgbw)
|
||
BCS.S @BLACK ; =>NOT WHITE
|
||
OR #$00E0,D0 ; ELSE SET WHITE BITS (CMY = 111)
|
||
@BLACK LSR #5,D0 ; SHIFT ICMY INTO LOW NIBBLE
|
||
AND #$7,D0 ; CLEAR ALL BUT CMY
|
||
MOVE.L QDColors,A0 ; GET DEFAULT COLORS
|
||
LEA 2(A0,D0*8),A0 ; point to proper entry
|
||
MOVE.L (A0)+,(A1)+ ; copy red, green
|
||
MOVE (A0)+,(A1)+ ; copy blue
|
||
BRA.S DONE ; => all done
|
||
|
||
;
|
||
; PROCEDURE GetBackColor (VAR Color: RGBColor);
|
||
;
|
||
; Return the RGB components of the current background color
|
||
; Works for old and new ports.
|
||
;
|
||
|
||
GetBackColor
|
||
|
||
MOVEQ #BKCOLOR,D0 ; get offset to the index field
|
||
MOVEQ #RGBBkColor,D1 ; get offset to RGB field
|
||
BRA.S SHARE ; and use common code
|
||
|
||
|
||
;
|
||
; function RealColor ( color : RGBColor ) : boolean;
|
||
;
|
||
; This call tests if the given RGBColor actually exists in the current
|
||
; device colortable. It is analogous to RealFont in the Font Manager.
|
||
; It tests if the best match to the provided color is actually in the
|
||
; device colortable rather than actually testing the color table elements.
|
||
;
|
||
|
||
RealColor FUNC EXPORT
|
||
|
||
result EQU 12
|
||
inCol EQU 8
|
||
I2CSpace EQU -6
|
||
|
||
LINK A6,#I2CSpace ; build a stack frame <C491/06Dec86> DAF
|
||
CLR.B result(A6) ; assume result false
|
||
SUBQ #4,SP ; make room for the function return <C491/06Dec86> DAF
|
||
MOVE.L inCol(A6),-(SP) ; push pointer to rgbColor <C491/06Dec86> DAF
|
||
_Color2Index ; find the index, leave result on stack <C491/06Dec86> DAF
|
||
PEA I2CSpace(A6) ; push pointer to rgbColor result <C491/06Dec86> DAF
|
||
_Index2Color ; get the device colorTable entry
|
||
|
||
MOVE.L ([theGDevice]),A0 ; get a pointer to the current device <C733/02Feb87> DAF
|
||
MOVE.L ([GDITable,A0]),A0 ; get the Itable's master pointer <C733/02Feb87> DAF
|
||
MOVE.W ITabRes(A0),D2 ; get the current iTable resolution <C733/02Feb87> DAF
|
||
|
||
BFEXTU ([inCol,A6]){0:D2},D0 ; get res hi bits of red input <C733/02Feb87> DAF
|
||
BFEXTU I2CSpace(A6){0:D2},D1 ; get res hi bits of red result <C733/02Feb87> DAF
|
||
CMP D0,D1 ; compare them <C733/02Feb87> DAF
|
||
BNE.S @0 ; if different then return FALSE <C733/02Feb87> DAF
|
||
|
||
BFEXTU ([inCol,A6],green){0:D2},D0 ; get res hi bits of grn input <C733/02Feb87> DAF
|
||
BFEXTU I2CSpace+green(A6){0:D2},D1 ; get res hi bits of grn result <C733/02Feb87> DAF
|
||
CMP D0,D1 ; compare them <C733/02Feb87> DAF
|
||
BNE.S @0 ; if different then return FALSE <C733/02Feb87> DAF
|
||
|
||
BFEXTU ([inCol,A6],blue){0:D2},D0 ; get res hi bits of blu input <C733/02Feb87> DAF
|
||
BFEXTU I2CSpace+blue(A6){0:D2},D1 ; get res hi bits of blu result <C733/02Feb87> DAF
|
||
CMP D0,D1 ; compare them <C733/02Feb87> DAF
|
||
BNE.S @0 ; if different then return FALSE <C733/02Feb87> DAF
|
||
|
||
MOVE.B #1,result(A6) ; the color exists, so set boolean TRUE
|
||
|
||
@0 UNLK A6 ; dump stack frame
|
||
RTD #4 ; and return <C491/06Dec86> DAF
|
||
|
||
|
||
;
|
||
; procedure SetEntries ( start,count : integer; aTable : ptr );
|
||
;
|
||
; This routine places the specified color into position index in the
|
||
; current device color table. The value field of this element is set to
|
||
; ownerID, which may include an owner ID number, as well as protect and
|
||
; reserve bits. If this value is zero, then the value is considered
|
||
; to be fair game for the system. After updating the GDevice data
|
||
; structures, the device's driver is called to actually change the
|
||
; lookup table.
|
||
;
|
||
|
||
SetEntries PROC EXPORT ; rewritten <C522/15Dec86> DAF
|
||
|
||
csc_SetEntries EQU 3 ; control call # for setEntries
|
||
|
||
Start EQU 14
|
||
Count EQU 12
|
||
Tbl EQU 8
|
||
SEPBlock EQU -csParam-4 ; parmBlock for control (32 bytes)
|
||
CParms EQU SEPBlock-8 ; control call parameters (8 bytes)
|
||
LinkSize EQU CParms
|
||
|
||
LINK A6,#LinkSize ; set up a stack frame
|
||
MOVEM.L A2/D3,-(SP) ; save some registers
|
||
|
||
; first, test to make sure the requested entries can be changed
|
||
|
||
MOVE.L ([theGDevice]),A0 ; get the master pointer to current device
|
||
MOVE.W GDID(A0),D2 ; get theGDevice's ownerID
|
||
CMP.W #CLUTType,GDType(A0) ; is this a changeable device?
|
||
BNE SEDevErr ; nope, so quit
|
||
|
||
; Mark QDSpare that the color environment has changed, but only if
|
||
; QD exists
|
||
TST.B QDExist ; is QD around?
|
||
BNE.S @noQDE ; no, skip this next
|
||
MOVE.L (A5),A2
|
||
BSET #3,QDSpare0(A2) ; Tell PMgrExit to do color cleaning
|
||
@noQDE
|
||
|
||
|
||
MOVE.L ([GDPMap,A0]),A0 ; get a pointer to the device pixmap
|
||
MOVE.L ([pmTable,A0]),A2 ; get a pointer to the device's color table
|
||
|
||
MOVE.W Count(A6),D1 ; get the count
|
||
MOVE.W Start(A6),D0 ; get the starting position
|
||
BMI.S IndexMode ; if minus, then index mode
|
||
|
||
SeqMode
|
||
ADD.W D1,D0 ; calc the last entry to change
|
||
CMP.W CTSize(A2),D0 ; compare to color table size <C751/03Feb87> DAF
|
||
BGT.S RangeErr ; if in legal range (≤), continue <C751/03Feb87> DAF
|
||
|
||
@0
|
||
BTST #protectBit,CTTable+value(A2,D0*8) ; test the protect bit <C751/03Feb87> DAF
|
||
BNE.S ProtError ; oh, oh. Can't changed a protected one!
|
||
BTST #ReserveBit,CTTable+value(A2,D0*8) ; test the reserve bit <C751/03Feb87> DAF
|
||
BEQ.S @1 ; if clear, then it can be changed <C751/03Feb87> DAF
|
||
CMP.B CTTable+value+1(A2,D0*8),D2 ; compare to current ClientID (byte only) <C751/03Feb87> DAF
|
||
BNE.S ProtError ; sorry, can't change someone else's <C751/03Feb87> DAF
|
||
@1
|
||
SUBQ #1,D0 ; back index up by one
|
||
DBRA D1,@0 ; loop back
|
||
BRA.S OKFine ; the request is valid
|
||
|
||
RangeErr
|
||
MOVE #cRangeErr,D0 ; if not, then return an error
|
||
BRA SEError ;
|
||
|
||
ProtError
|
||
MOVE #cProtectErr,D0 ;
|
||
BRA SEError
|
||
|
||
IndexMode ; test the .value fields in INDEX mode
|
||
MOVE.L Tbl(A6),A0 ; get addr of first request
|
||
@0
|
||
MOVE.W value(A0),D0 ; get the destination location from request array
|
||
AND.W #$00FF,D0 ; lo-byte only for index
|
||
CMP.W CTSize(A2),D0 ; is the request in range? <C835/20Feb87> DAF
|
||
BGT.S RangeErr ; nope, so quit <C835/20Feb87> DAF
|
||
BTST #protectBit,CTTable+value(A2,D0*8) ; test the protect bit <C751/03Feb87> DAF
|
||
BNE.S ProtError ; oh, oh. Can't changed a protected one!
|
||
BTST #ReserveBit,CTTable+value(A2,D0*8) ; test the reserve bit <C751/03Feb87> DAF
|
||
BEQ.S @1 ; if clear, then it can be changed <C751/03Feb87> DAF
|
||
CMP.B CTTable+value+1(A2,D0*8),D2 ; compare to current ClientID (byte only) <C751/03Feb87> DAF
|
||
BNE.S ProtError ; sorry, can't change someone else's <C751/03Feb87> DAF
|
||
@1
|
||
ADDQ #CTEntrySize,A0 ; move to next entry
|
||
DBRA D1,@0 ; reduce count
|
||
|
||
OKFine
|
||
|
||
MOVE.W Start(A6),CParms+csStart(A6) ; set up control parm block
|
||
MOVE.W Count(A6),CParms+csCount(A6) ;
|
||
MOVE.L Tbl(A6),CParms+csTable(A6) ;
|
||
|
||
; now build a parameter block for a control call (in stack frame)
|
||
|
||
MOVE.L #0,SEPBlock+ioCompletion(A6) ; no completion routine
|
||
MOVE.W #0,SEPBlock+ioVRefNum(A6) ; device not volume
|
||
MOVE.L ([theGDevice]),A1 ; get ptr to theGDevice
|
||
MOVE.W (A1),SEPBlock+ioRefNum(A6) ; copy refNum from theGDevice
|
||
MOVE.W #csc_SetEntries,SEPBlock+csCode(A6) ; control code for this call
|
||
LEA CParms(A6),A1 ; get addr of parms
|
||
MOVE.L A1,SEPBlock+csParam(A6) ; move addr of parms into block
|
||
|
||
; make a call to the device driver
|
||
|
||
LEA SEPBlock(A6),A0 ; get pointer to parmblock
|
||
_Control ,IMMED ; make a control call <C695/26Jan87> DAF
|
||
|
||
; test result and finish up
|
||
|
||
TST.W D0 ; test the result
|
||
BNE.S SEError
|
||
|
||
; put the RGBs into theGDevice's colortable. Copy the current ownerID into .value
|
||
; (wait until control call returns successfully!). D2 has GDID in it from above
|
||
|
||
MOVE.L Tbl(A6),A0 ; get the request array ptr
|
||
MOVE.W Count(A6),D0 ; get the number of entries to install
|
||
MOVE.W Start(A6),D1 ; get the starting position number
|
||
BMI.S InstIndex ; if minus, then INDEX mode
|
||
|
||
InstSeq
|
||
LEA CTTable(A2,D1*8),A1 ; get ptr to start position in sysColorTable
|
||
@0
|
||
ADDQ #1,A1 ; advance to lo half of value <C777/09Feb87> DAF
|
||
MOVE.B D2,(A1)+ ; set value field to ownerID <C777/09Feb87> DAF
|
||
|
||
MOVE.L (A0)+,D3 ; get request value (junk) and red
|
||
MOVE.W D3,(A1)+ ; set red
|
||
MOVE.L (A0)+,(A1)+ ; set green and blue
|
||
DBRA D0,@0 ; loop for all requests
|
||
BRA.S FinishUp ;
|
||
|
||
InstIndex
|
||
MOVE.W (A0)+,D3 ; get the insertion index (.value field)
|
||
MOVE.B D2,CTTable+value+1(A2,D3*8) ; set value field to the ownerID <C777/09Feb87> DAF
|
||
MOVE.W (A0)+,CTTable+rgb+red(A2,D3*8) ; set red
|
||
MOVE.L (A0)+,CTTable+rgb+green(A2,D3*8) ; set green and blue
|
||
DBRA D0,InstIndex ; loop for all entries
|
||
|
||
FinishUp
|
||
; update the CTSeed
|
||
|
||
CLR.L -(SP) ; make room for function return
|
||
_rGetCTSeed ; get the next seed <BAL 04Sep88>
|
||
MOVE.L (SP)+,CTSeed(A2) ; and put it in the table
|
||
|
||
; invalidate the cached fonts
|
||
|
||
MOVE.L MinusOne,lastSPExtra ; this marks them invalid <C777/12Feb87> DAF
|
||
|
||
SEDone
|
||
MOVEM.L (SP)+,A2/D3 ; restore saved registers
|
||
UNLK A6 ; dump stack frame
|
||
RTD #8
|
||
|
||
SEDevErr MOVE.W #cDevErr,D0 ; wrong device type error
|
||
SEError
|
||
MOVE.W D0,QDErr ; record the error code <C367/07Nov86> DAF
|
||
BRA.S SEDone ; and finish up <C367/07Nov86> DAF
|
||
|
||
|
||
;
|
||
; procedure RestoreEntries (srcTable:cTabHandle; DstTable:cTabHandle; var selection:requestList);
|
||
;
|
||
; RestoreEntries sets a selection of entries from srcTable into DstTable. The dstTable elements
|
||
; to be set are enumerated in selection (these values are offsets into the srcTable,
|
||
; not the contents of the value field). If a request is beyond the end of the dstTable,
|
||
; that position of the requestList is set to invalColReq, and is not installed into dstTable.
|
||
; This call does not observe the reserve and protect fields of entries in dstTable.
|
||
; If DstTable is NIL (or = to theGDevice's colortable), then srcTable is installed into
|
||
; theGDevice's colortable, and the CLUT is set to the new values. Note that srcTable and
|
||
; selection are assumed to have the same number of elements.
|
||
;
|
||
|
||
RestoreEntries PROC EXPORT
|
||
|
||
csc_SetEntries EQU 3 ; control call # for setEntries
|
||
|
||
; stack frame declarations
|
||
SrcT EQU 16
|
||
dstT EQU 12
|
||
RLst EQU 8
|
||
SEPBlock EQU -csParam-4 ; parmBlock for control (36 bytes)
|
||
CParms EQU SEPBlock-8 ; control call parameters (8 bytes)
|
||
LinkSize EQU CParms ; size of stack frame locals
|
||
|
||
LINK A6,#LinkSize ;
|
||
MOVEM.L A2/A3/D3,-(SP) ; save some registers
|
||
CLR.W QDErr ; clear error register
|
||
MOVE.L ([SrcT,A6]),A2 ; get source colortable ptr
|
||
MOVE.L RLst(A6),A1 ; get the request list ptr
|
||
MOVE.W ReqLSize(A1),D2 ; get the request list size
|
||
|
||
MOVE.L ([theGDevice]),A0 ; get a pointer to the current device
|
||
CMP.W #CLUTType,GDType(A0) ; is it a clut device?
|
||
BNE REDevErr ; nope, so report an error
|
||
MOVE.L ([GDPMap,A0]),A0 ; get pixMap's handle <C239> DAF
|
||
MOVE.L ([PMTable,A0]),A0 ; get a pointer to the device colortable <C239> DAF
|
||
|
||
MOVE.L ([dstT,A6]),A3 ; get destination colortable ptr in case it's OK
|
||
CMP.L A0,A3 ; does dest point to theGDevice's colortable?
|
||
BEQ.S @8 ; so do the control call
|
||
TST.L dstT(A6) ; is destination NIL?
|
||
BNE.S JustInstall ; if non-NIL, then just install the srcTbl
|
||
MOVE.L A0,A3 ; move the device colortable ptr to A3
|
||
@8
|
||
|
||
; if DstTbl was NIL or (ptr) equal, then dest is theGDevice's colortable...
|
||
; save the value fields of the srcTable on the stack
|
||
|
||
MOVEQ #0,D1 ; clear hi half of D0
|
||
MOVE.W D2,D1 ; make a copy of the srcTable size
|
||
ADDQ #1,D1 ; adjust from count to size
|
||
ASL #1,D1 ; times two for words
|
||
SUBA D1,SP ; make room for these values on stack
|
||
MOVE.W D2,D0 ; get # of value fields to move
|
||
@0
|
||
MOVE.W CTTable+value(A2,D0*8),(SP,D0*2) ; copy the values
|
||
DBRA D0,@0 ;
|
||
|
||
; now install the position fields into the srcTable
|
||
|
||
MOVE.W D2,D0 ; get # of value fields to move
|
||
@1
|
||
MOVE.W ReqLData(A1,D0*2),D3 ; get the target position
|
||
CMP.W CTSize(A3),D3 ; compare to the maximum for this destination
|
||
BGT LeakError ; if out of range, return error (Bruce wanted this)
|
||
MOVE.W D3,CTTable+value(A2,D0*8) ; write the request in the source table
|
||
DBRA D0,@1 ;
|
||
|
||
; at this point, the "bad" entries should be removed, but we can leave them
|
||
; for now since the driver will range test positions (and invalColReq >256).
|
||
|
||
; make a driver call with the modified src table
|
||
|
||
MOVE.L #0,SEPBlock+ioCompletion(A6) ; no completion routine
|
||
MOVE.W #0,SEPBlock+ioVRefNum(A6) ; device not volume
|
||
MOVE.L ([theGDevice]),A0 ; get ptr to theGDevice
|
||
MOVE.W (A0),SEPBlock+ioRefNum(A6) ; copy refNum from theGDevice
|
||
MOVE.W #csc_SetEntries,SEPBlock+csCode(A6) ; control code for this call
|
||
LEA CParms(A6),A0 ; get addr of parms
|
||
MOVE.L A0,SEPBlock+csParam(A6) ; move addr of parms into block
|
||
|
||
; set up control call parameters
|
||
|
||
LEA CTTable(A2),A0 ; get pointer to the colorspecs
|
||
MOVE.L A0,cParms+csTable(A6) ; put in parameter block
|
||
MOVE.W #-1,cParms+csStart(A6) ; always use index mode
|
||
MOVE.W D2,cParms+csCount(A6) ; for the correct size
|
||
|
||
; make a call to the device driver
|
||
|
||
LEA SEPBlock(A6),A0 ; get pointer to parmblock
|
||
_Control ,IMMED ; make a control call <C695/26Jan87> DAF
|
||
|
||
; test result and finish up
|
||
|
||
BEQ.S ReleaseSP ; call went ok, so continue
|
||
MOVE.W D0,QDErr ; report the control code error
|
||
|
||
; finally, restore the src table value fields
|
||
ReleaseSP
|
||
MOVE.W D2,D0 ; get # of value fields to move
|
||
@2
|
||
MOVE.W (SP,D0*2),CTTable+value(A2,D0*8) ; copy the values
|
||
DBRA D0,@2 ;
|
||
|
||
ADDA D1,SP ; release the temporary space
|
||
|
||
JustInstall
|
||
MOVE.W ReqLData(A1,D2*2),D0 ; get the request index
|
||
CMP.W #invalColReq,D0 ; if the request is bad, skip it
|
||
BEQ.S JLoopCont ;
|
||
CMP.W CTSize(A3),D0 ; is it in the legal range?
|
||
BGT.S JIErr ; if not, then return an error
|
||
MOVE.L CTTable(A2,D2*8),CTTable(A3,D0*8) ; copy value and red
|
||
MOVE.L CTTable+rgb+green(A2,D2*8),CTTable+rgb+green(A3,D0*8) ;copy green and blue
|
||
JLoopCont
|
||
DBRA D2,JustInstall ; loop back
|
||
Exeunt
|
||
TST.L dstT(A6) ; if NIL, was a device call, so call the Palette Mgr
|
||
BNE.S Moofem ; nope, so skip around
|
||
MOVE.L RLst(A6),-(SP) ; push the request list pointer
|
||
MOVE #18,D0 ; this is the selector for the _ReleaseList call
|
||
DC.W $AAA2 ; this is the extensible PaletteMgr trap
|
||
Moofem
|
||
MOVEM.L (SP)+,A2/A3/D3 ; restore work registers
|
||
UNLK A6 ; release stack frame
|
||
RTD #12 ; and return to caller
|
||
|
||
JIErr
|
||
MOVE.W #cRangeErr,QDErr ; move error message into QDErr
|
||
BRA.S JLoopCont ; continue
|
||
REDevErr
|
||
MOVE.W #cDevErr,QDErr ;
|
||
BRA.S Moofem ;
|
||
|
||
; If ANY of the requests are out of range, then leave the whole call without doing anything. Bruce
|
||
; asked for this change since ancient users of Save/RestoreEntries (PixelPaint and Color Picker)
|
||
; will trash the system with RestoreEntries if they were Switcheroo'd into a different depth. This
|
||
; ONLY protects you if you are switching to a lower pixel depth, but it helps out a lot in those
|
||
; cases
|
||
LeakError
|
||
MOVE.W #cRangeErr,QDErr ; report an error
|
||
MOVE.W D2,D0 ; get # of value fields to move
|
||
@2
|
||
MOVE.W (SP,D0*2),CTTable+value(A2,D0*8) ; restore the sourcetable values
|
||
DBRA D0,@2 ;
|
||
|
||
ADDA D1,SP ; release the temporary space
|
||
BRA.S Exeunt ; and out
|
||
|
||
;
|
||
; procedure SaveEntries (srcTable:cTabHandle; ResultTable:cTabHandle; var selection:requestList);
|
||
;
|
||
; SaveEntries saves a selection of entries from srcTable into ResultTable. The elements
|
||
; to be copied are enumerated in selection (these values are offsets into the colorTable,
|
||
; not the contents of the value field). If an element is not present in srcTable, then
|
||
; that position of the requestList is set to invalColReq, and that position of ResultTable has random
|
||
; values returned. If one or more elements are not found, then an error code is posted
|
||
; to QDErr; however, for every element in selection which is not -1, the values in ResultTable
|
||
; are valid. Note that srcTable and selection are assumed to have the same number
|
||
; of elements.
|
||
;
|
||
|
||
SaveEntries PROC EXPORT
|
||
|
||
SrcT EQU 16
|
||
ResT EQU 12
|
||
RLst EQU 8
|
||
|
||
LINK A6,#0 ;
|
||
MOVE.L A2,-(SP) ; save a register
|
||
CLR.W QDErr ; clear error register
|
||
TST.L SrcT(A6) ; if source is NIL, use theGDevice's ctable
|
||
BNE.S @80 ;
|
||
|
||
MOVE.L ([theGDevice]),A0 ; get a pointer to the current device
|
||
CMP.W #CLUTType,GDType(A0) ; is it a CLUT device? <1.4>
|
||
BNE.S SavEntDevErr ; nope, so report an error <1.4> <SM3>
|
||
MOVE.L ([GDPMap,A0]),A0 ; get pixMap's handle <C239> DAF
|
||
MOVE.L ([PMTable,A0]),A2 ; get a pointer to the device colortable <C239> DAF
|
||
BRA.S @81 ; and continue
|
||
@80
|
||
MOVE.L ([SrcT,A6]),A2 ; get source colortable ptr
|
||
@81
|
||
MOVE.L RLst(A6),A1 ; get the request list ptr
|
||
MOVE.W ReqLSize(A1),D2 ; get the request list size
|
||
MOVE.W D2,D0 ; copy size to a temp register
|
||
ADDQ #1,D0 ; increase by one for size calculations
|
||
MULU #CTEntrySize,D0 ; calc the result table size
|
||
ADDQ #CTTable,D0 ; add the header size
|
||
MOVE.L ResT(A6),A0 ; get the result table handle
|
||
TST.L (A0) ; is the master pointer NIL?
|
||
BEQ.S @0 ; if so, do a realloc
|
||
_SetHandleSize ; set the result table size
|
||
BRA.S @1 ;
|
||
@0
|
||
_ReallocHandle ;
|
||
@1
|
||
BEQ.S @2
|
||
MOVE.W #CNoMemErr,QDErr ; mark the error <C621/13Jan87> DAF
|
||
BRA.S SaveEntDone ; and quit <C621/13Jan87> DAF <SM3>
|
||
@2
|
||
MOVE.L (A0),A0 ; get a pointer to the result table
|
||
MOVE.L #0,CTSeed(A0) ; clear CTSeed
|
||
MOVE.W #0,TransIndex(A0) ; clear transparent value
|
||
MOVE.W D2,CTSize(A0) ; #elements = size of request table
|
||
SavLoop
|
||
MOVE.W ReqLData(A1,D2*2),D0 ; get the request value
|
||
CMP.W CTSize(A2),D0 ; is it in the allowable range? <C491/08Dec86> DAF
|
||
BGT.S SaveEntRangeErr ; no, so mark an error <SM3>
|
||
MOVE.L CTTable(A2,D0*8),CTTable(A0,D2*8) ;move value and red to result table
|
||
MOVE.L CTTable+rgb+green(A2,D0*8),CTTable+rgb+green(A0,D2*8) ; green and blue
|
||
SLoopCont
|
||
DBRA D2,SavLoop ; go on to the next request
|
||
SaveEntDone ; <SM3>
|
||
MOVE.L (SP)+,A2 ; restore that register
|
||
UNLK A6 ; trash the stack frame
|
||
RTD #12 ; and return <SM3>
|
||
|
||
SaveEntRangeErr ; <SM3>
|
||
MOVE.W #invalColReq,ReqLData(A1,D2*2) ; mark this element invalid
|
||
MOVE.W #cRangeErr,QDErr ; move error message into QDErr
|
||
BRA.S SLoopCont ; continue
|
||
|
||
SavEntDevErr ; <1.4><1.5><SM3>
|
||
MOVE.W #cDevErr,QDErr ; post error code <1.4><SM3>
|
||
BRA.S SaveEntDone ; and quit <1.4><SM3>
|
||
|
||
|
||
;
|
||
; procedure ProtectEntry (index : integer; protect : boolean);
|
||
;
|
||
; ProtectEntry sets the protect bit in theGDevice's colortable. If
|
||
; protect is TRUE, then the bit is set and SetEntry will not change
|
||
; it. If protect is FALSE, then the bit is cleared and the CLUT can
|
||
; be changed.
|
||
;
|
||
|
||
ProtectEntry PROC EXPORT
|
||
EXPORT ReserveEntry
|
||
|
||
MOVEQ #protectBit,D2 ; this call modifies the protect bit
|
||
BSR.S CTCommon ; do it
|
||
OneQuit ; <C751/03Feb87> DAF
|
||
RTD #4 ;
|
||
|
||
ProtErr
|
||
MOVE.W #cProtectErr,QDErr ; mark the error <C751/03Feb87> DAF
|
||
BRA.S RErrQ ; jump to common exit <C751/03Feb87> DAF
|
||
|
||
RangeErr
|
||
MOVE.W #cRangeErr,QDErr ; mark the error <C751/03Feb87> DAF
|
||
RErrQ
|
||
ADDQ #4,SP ; kill the BSR's return addr <C751/03Feb87> DAF
|
||
BRA.S OneQuit ; use ProtectEntry's (both have same cleanup) <C751/03Feb87> DAF
|
||
|
||
;
|
||
; utility CTCommon
|
||
;
|
||
; CTCommon is a utility shared by ProtectEntry and Reserve entry. It
|
||
; sets/clears the bit (whose mod 8 position is in D2) in theGDevice's
|
||
; colortable. It trashes A1/D1 and ReserveEntry expects A0 to contain
|
||
; a pointer to the colorTable and D0 to be the affected index.
|
||
; Corrected offsets into stack frame and scaling (C575)
|
||
|
||
CTCommon
|
||
CLR.W QDErr ; clear the error flag <C751/03Feb87> DAF
|
||
MOVE.L ([theGDevice]),A0 ; get the current device pointer
|
||
MOVE.L ([GDPMap,A0]),A0 ; get the device pixelmap pointer
|
||
MOVE.L ([pmTable,A0]),A0 ; point to the color table
|
||
MOVE.W 10(SP),D0 ; get the index <C575/30Dec86> DAF
|
||
CMP.W CTSize(A0),D0 ; is it in the legal range? <C751/03Feb87> DAF
|
||
BGT.S RangeErr ; oops, out of range <C751/03Feb87> DAF
|
||
TST.B 8(SP) ; test the boolean <C575/30Dec86> DAF
|
||
BEQ.S @1 ; if equal, then clear bit
|
||
BTST D2,CTTable+value(A0,D0.W*8) ; if bit already on? <C751/03Feb87> DAF
|
||
BNE.S ProtErr ; if so, return error <C751/03Feb87> DAF
|
||
BSET D2,CTTable+value(A0,D0.W*8) ; turn bit on <C575/30Dec86> DAF
|
||
BRA.S @2 ;
|
||
@1 BCLR D2,CTTable+value(A0,D0.W*8) ; turn bit off <C575/30Dec86> DAF
|
||
@2
|
||
RTS
|
||
|
||
;
|
||
; procedure ReserveEntry (index : integer; reserve : boolean);
|
||
;
|
||
; ReserveEntry sets the reserve bit in theGDevice's colortable. If
|
||
; reserve is TRUE, then this CLUT element will not be seeded during
|
||
; ITable building and will not be a treated as an available color.
|
||
; Additionally, if reserve is TRUE, the value field will be marked
|
||
; with the current GDID (for symmetry with SetEntries).
|
||
; If reserve is FALSE, then the bit is cleared and this entry
|
||
; can be a match. The clientID of this entry is not affected
|
||
;
|
||
|
||
ReserveEntry
|
||
|
||
MOVEQ #ReserveBit,D2 ; this call modifies the reserve bit
|
||
BSR.S CTCommon ; do it
|
||
TST.B 4(SP) ; is reserve true? <C751/03Feb87> DAF
|
||
BEQ.S @1 ; if false, then done <C751/03Feb87> DAF
|
||
MOVE.W CTTable+value(A0,D0.W*8),D1 ; get value field of affected colorSpec <C751/03Feb87> DAF
|
||
MOVE.L ([theGDevice]),A1 ; get pointer to theGDevice <C751/03Feb87> DAF
|
||
MOVE.B GDID+1(A1),CTTable+value+1(A0,D0.W*8) ; set clientID (lo byte of GDID) <C777/09Feb87> DAF
|
||
|
||
@1
|
||
CLR.L -(SP) ; make room for function return <C777/09Feb87> DAF
|
||
_rGetCTSeed ; get the next seed <BAL 04Sep88>
|
||
MOVE.L (SP)+,CTSeed(A0) ; and put it in the table <C777/09Feb87> DAF
|
||
RTD #4 ; return to caller
|
||
|
||
;
|
||
; procedure SetClientID ( id : integer );
|
||
;
|
||
; SetClientID updates the clientID field of theGDevice. This field is
|
||
; used by the search and complement procedures to determine if they
|
||
; should operate on a particular request.
|
||
|
||
SetClientID PROC EXPORT
|
||
MOVE.L ([theGDevice]),A0 ; get the current device pointer
|
||
MOVE.W 4(SP),GDID(A0) ; set it
|
||
RTD #2 ; return
|
||
|
||
;
|
||
; procedure AddSearch (SearchProc : ProcPtr);
|
||
;
|
||
; This routine adds a search procedure to the head of the list of
|
||
; searchprocs in theGDevice.
|
||
;
|
||
|
||
AddSearch PROC EXPORT
|
||
EXPORT AddComp
|
||
|
||
CLR.W QDErr ; clear the error register <C387/09Nov86> DAF
|
||
MOVE.L (SP)+,D2 ; grab the return address
|
||
MOVE.L (SP)+,D1 ; grab the searchProc pointer
|
||
BEQ.S AllDone ; if NIL, don't install
|
||
MOVE.L #sProcSize,D0 ; allocate a new proc element
|
||
_NewHandle ; get that memory <C666/22Jan87> DAF
|
||
BNE.S ProcMemFailure ; couldn't get it
|
||
|
||
move.l d1,d0 ; get procPtr in d0 <BAL 14Mar89>
|
||
_rTranslate24to32 ; clean up the address <BAL 14Mar89>
|
||
|
||
MOVE.L ([theGDevice]),A1 ; get the current device pointer
|
||
MOVE.L GDSearchProc(A1),D1 ; hold the current search proclist element
|
||
MOVE.L A0,GDSearchProc(A1) ; install the new element
|
||
MOVE.L (A0),A0 ; get the procList pointer <C666/22Jan87> DAF
|
||
MOVE.L D0,SRCHPROC(A0) ; put in the list <C666/22Jan87> DAF
|
||
MOVE.L D1,NXTSRCH(A0) ; link up chain <C666/22Jan87> DAF
|
||
|
||
; Get a unique seed for this device to force the search proc to get called and the Itab rebuilt
|
||
; <BAL/dvb/RAJ 03Mar89>
|
||
; Removed for PhotoMac compatibility <BAL 26Mar89>
|
||
; MOVE.L ([GDPMap,A1]),A1 ; get the device pixelmap pointer
|
||
; MOVE.L pmTable(A1),d0 ; get the device clut handle <BAL 21Mar89>
|
||
; beq.s AllDone ; skip if no clut <BAL 21Mar89>
|
||
; move.l d0,a1
|
||
; MOVE.L (a1),A1 ; get the device clut pointer
|
||
; CLR.L -(SP) ; make room for function return
|
||
; _rGetCTSeed ; get the next seed
|
||
; MOVE.L (SP)+,CTSeed(A1) ; and put it in the table <BAL/dvb/RAJ 03Mar89>
|
||
AllDone JMP (ZA0,D2.L) ; return home
|
||
|
||
|
||
ProcMemFailure
|
||
MOVE.W #cNoMemErr,QDErr ; load memory error code <C387/09Nov86> DAF
|
||
BRA.S AllDone ; <C387/09Nov86> DAF
|
||
|
||
;
|
||
; procedure AddComp (CompProc : ProcPtr);
|
||
;
|
||
; This routine adds a complement procedure to the head of the list of
|
||
; compprocs in theGDevice.
|
||
;
|
||
|
||
AddComp
|
||
|
||
CLR.W QDErr ; clear the error register <C666/22Jan87> DAF
|
||
MOVE.L (SP)+,D2 ; grab the return address
|
||
MOVE.L (SP)+,D1 ; grab the compProc pointer
|
||
BEQ.S AllDunn ; if NIL, don't install
|
||
MOVE.L #sProcSize,D0 ; allocate a new proc element
|
||
_NewHandle ; get that memory <C666/22Jan87> DAF
|
||
BNE.S ProcMemFailure ; couldn't get it
|
||
|
||
move.l d1,d0 ; get procPtr in d0 <BAL 14Mar89>
|
||
_rTranslate24to32 ; clean up the address <BAL 14Mar89>
|
||
|
||
MOVE.L ([theGDevice]),A1 ; get the current device pointer
|
||
MOVE.L GDCompProc(A1),D1 ; hold the current complement proclist element <C666/22Jan87> DAF
|
||
MOVE.L A0,GDCompProc(A1) ; install the new element
|
||
MOVE.L (A0),A0 ; get procList pointer <C666/22Jan87> DAF
|
||
MOVE.L D0,COMPPROC(A0) ; put in the list <C666/22Jan87> DAF
|
||
MOVE.L D1,NXTCOMP(A0) ; link up chain <C666/22Jan87> DAF
|
||
AllDunn JMP (ZA0,D2.L) ; return home
|
||
|
||
|
||
;
|
||
; procedure DelSearch ( SearchProc : ProcPtr );
|
||
;
|
||
; This routine removes a search proc (identified by it's procPtr from theGDevice's search list
|
||
;
|
||
|
||
; contains fix from QDciPatchROM.a to clean up the address before searching <sm 6/9/92>stb
|
||
|
||
DelSearch PROC EXPORT ; <C666/22Jan87> DAF
|
||
|
||
MOVE.L 4(SP),D0 ; get the SearchProc pointer
|
||
_rTranslate24to32 ; clean up the address <KON 29May90>
|
||
|
||
MOVE.L ([theGDevice]),A1 ; get the current device pointer
|
||
|
||
; Get a unique seed for this device to force the Itab to get rebuilt <BAL/dvb/RAJ 03Mar89>
|
||
|
||
; Removed for PhotoMac compatibility <BAL 26Mar89>
|
||
; MOVE.L ([GDPMap,A1]),A0 ; get the device pixelmap pointer <BAL/dvb/RAJ 03Mar89>
|
||
; MOVE.L pmTable(A0),d0 ; get the device clut handle <BAL 21Mar89>
|
||
; beq.s skipSeed ; skip if no clut <BAL 21Mar89>
|
||
; move.l d0,a0
|
||
; MOVE.L (a0),A0 ; get the device clut pointer
|
||
; CLR.L -(SP) ; make room for function return <BAL/dvb/RAJ 03Mar89>
|
||
; _rGetCTSeed ; get the next seed <BAL/dvb/RAJ 03Mar89>
|
||
; MOVE.L (SP)+,CTSeed(A0) ; and put it in the table <BAL/dvb/RAJ 03Mar89>
|
||
skipSeed
|
||
LEA GDSearchProc(A1),A1 ; get pointer to "nxtSearch" field
|
||
MOVE.L (A1),D2 ; hold the current search proclist handle
|
||
|
||
@1
|
||
BEQ.S DSrchDone ; if nil, then end of chain
|
||
MOVE.L D2,A0 ; copy to an addr register
|
||
MOVE.L (A0),A0 ; get the pointer to proc list elem
|
||
CMP.L srchProc(A0),D0 ; do they match?
|
||
BEQ.S RmvSrch ; yes, so splice it out
|
||
LEA NxtSrch(A0),A1 ; get addr of this NxtSrch field
|
||
MOVE.L NxtSrch(A0),D2 ; go to the next one
|
||
BRA.S @1
|
||
RmvSrch
|
||
MOVE.L NxtSrch(A0),(A1) ; relink the chain around this element
|
||
MOVE.L D2,A0 ; setup for Dispose
|
||
_DisposHandle ; dispose the procLstElem
|
||
DSrchDone
|
||
RTD #4 ; strip params and return
|
||
|
||
|
||
;
|
||
; procedure DelComp ( complementProc : ProcPtr );
|
||
;
|
||
; This routine removes a complement proc (identified by it's procPtr from theGDevice's search list
|
||
;
|
||
; contains fix from QDciPatchROM.a to clean up the address before searching <sm 6/9/92>stb
|
||
|
||
DelComp PROC EXPORT ; <C666/22Jan87> DAF
|
||
|
||
MOVE.L 4(SP),D0 ; get the CompProc pointer
|
||
_rTranslate24to32 ; clean up the address <KON 29May90>
|
||
MOVE.L ([theGDevice]),A1 ; get the current device pointer
|
||
LEA GDCompProc(A1),A1 ; get pointer to "nxtComp" field
|
||
MOVE.L (A1),D2 ; hold the current complement proclist handle
|
||
|
||
@1
|
||
BEQ.S DCompDone ; if nil, then end of chain
|
||
MOVE.L D2,A0 ; copy to an addr register
|
||
MOVE.L (A0),A0 ; get the pointer to proc list elem
|
||
CMP.L CompProc(A0),D0 ; do they match?
|
||
BEQ.S RmvComp ; yes, so splice it out
|
||
LEA NxtComp(A0),A1 ; get addr of this NxtSrch field
|
||
MOVE.L NxtComp(A0),D2 ; go to the next one
|
||
BRA.S @1
|
||
RmvComp
|
||
MOVE.L NxtComp(A0),(A1) ; relink the chain around this element
|
||
MOVE.L D2,A0 ; setup for Dispose
|
||
_DisposHandle ; dispose the procLstElem
|
||
DCompDone
|
||
RTD #4 ; strip params and return
|
||
|
||
|
||
;
|
||
; procedure GetSubTable (VAR myColors:CTabHandle;
|
||
; iTabRes:integer;
|
||
; TargetTbl:CTabHandle);
|
||
;
|
||
; This routine takes a colorTable pointed at by myColors, and determines
|
||
; the best match index values for each rgb in myColors. These best
|
||
; matches are returned in the .value fields of myColor's colorSpecs.
|
||
; The values returned are best matches to the RGBs in TargetTbl and
|
||
; the returned indices are TargetTbl's .values. Best matches are
|
||
; calculated using Color2Index and all applicable rules apply.
|
||
; iTabRes controls the channel size of the iTable that is built.
|
||
; If TargetTbl is NIL, then theGDevice's colortable is used as the target
|
||
; and no inverse table is built.
|
||
;
|
||
|
||
GetSubTable PROC EXPORT
|
||
|
||
; offsets to parameters ; offsets corrected <C491/06Dec86> DAF
|
||
myColors EQU 14 ;
|
||
iTabResolution EQU 12 ;
|
||
TargetTbl EQU 8 ;
|
||
ITHndl EQU -4 ; temporary handle for iTable
|
||
SavHndl EQU -8 ; save theGDevice's iTable here
|
||
SavCol EQU -12 ; save theGDevice's colortable here <CXXX>
|
||
LinkSize EQU SavCol ; <CXXX>
|
||
|
||
LINK A6,#LinkSize ; make a stack frame
|
||
MOVEM.L A2/D3,-(SP) ; save some registers <C491/06Dec86> DAF
|
||
TST.L TargetTbl(A6) ; is target table NIL?
|
||
BEQ.S @UseOldTable ; nope, so make an ITable
|
||
|
||
_NewEmptyHandle ; make a temp handle for iTable
|
||
MOVE.L A0,ITHndl(A6) ; save the handle
|
||
MOVE.L TargetTbl(A6),-(SP) ; push the source cTable
|
||
MOVE.L A0,-(SP) ; push the iTable handle
|
||
MOVE.W iTabResolution(A6),-(SP) ; push the resolution
|
||
_MakeITable ; make an inverse table
|
||
|
||
TST.W QDErr ; did it fail? <C777/09Feb87> DAF
|
||
BNE.S @BailOut ; clean up an quit leaving the QDErr <C777/09Feb87> DAF
|
||
|
||
MOVE.L ([theGDevice]),A1 ; get a pointer to the device port
|
||
MOVE.L GDITable(A1),SavHndl(A6) ; save the current iTable here
|
||
MOVE.L ITHndl(A6),GDITable(A1) ; and substitute this iTable
|
||
MOVE.L ([GDPMap,A1]),A1 ; get pixMap's pointer <C777/09Feb87> DAF
|
||
MOVE.L PMTable(A1),SavCol(A6) ; save the current colorTable here <CXXX>
|
||
MOVE.L myColors(A6),PMTable(A1) ; and substitute this colorTable <CXXX>
|
||
MOVE.L ([PMTable,A1]),A1 ; copy colorTable's ctSeed into iTable <C695/26Jan87> DAF
|
||
MOVE.L ctSeed(A1),D0 ; get the ctSeed (to avoid rebuilds) <C695/26Jan87> DAF
|
||
MOVE.L ([ITHndl,A6]),A1 ; copy seed into the temp inverseTable <C695/26Jan87> DAF
|
||
MOVE.L D0,ITabSeed(A1) ; put seed into the iTable <C695/26Jan87> DAF
|
||
|
||
@UseOldTable
|
||
MOVE.L myColors(A6),A0 ; get source's cTabHndl
|
||
_HLock ; just for security <C491/06Dec86> DAF
|
||
MOVE.L (A0),A2 ; get a pointer <C491/06Dec86> DAF
|
||
MOVE.W CTSize(A2),D3 ; get the number of entries <C491/06Dec86> DAF
|
||
|
||
@0
|
||
SUBQ #4,SP ; make room for function return <C491/06Dec86> DAF
|
||
PEA CTTable+rgb(A2,D3*8) ; push the entry's rgb addr <C491/06Dec86> DAF
|
||
_Color2Index ; get the value
|
||
ADDQ #2,SP ; throw away hi word of result <C491/06Dec86> DAF
|
||
MOVE.W (SP)+,CTTable+value(A2,D3*8) ; place result in table <C491/06Dec86> DAF
|
||
DBRA D3,@0 ; loop on all entries
|
||
|
||
MOVE.L myColors(A6),A0 ; get source's cTabHndl <C491/06Dec86> DAF
|
||
_HUnlock ; and free it <C491/06Dec86> DAF
|
||
|
||
TST.L TargetTbl(A6) ; was it NIL?
|
||
BEQ.S @1 ; if it was, then skip the restorations
|
||
|
||
MOVE.L ([theGDevice]),A1 ; get a pointer to the device port
|
||
MOVE.L SavHndl(A6),GDITable(A1) ; restore the device inverse table
|
||
MOVE.L ([GDPMap,A1]),A1 ; get pixMap's pointer <C777/09Feb87> DAF
|
||
MOVE.L SavCol(A6),PMTable(A1) ; and substitute this colorTable <CXXX>
|
||
@BailOut
|
||
MOVE.L ITHndl(A6),A0 ; get the temp iTabHndl again
|
||
_DisposHandle ; all done, so dispose
|
||
@1
|
||
MOVEM.L (SP)+,A2/D3 ; restore saved registers <C666/22Jan87> DAF
|
||
UNLK A6 ; release stack frame
|
||
RTD #10 ; return <C491/06Dec86> DAF
|
||
|
||
|
||
;
|
||
; function QDError : integer; <C387/09Nov86> DAF
|
||
;
|
||
; This function returns the current value of QDErr, which reflects error conditions
|
||
; following the previous QuickDraw/Color Manager call.
|
||
;
|
||
|
||
QDError PROC EXPORT
|
||
|
||
MOVE.W QDErr,4(SP) ; move error code to function return
|
||
CLR.W QDErr ; and clear the code
|
||
RTS
|
||
|
||
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; 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
|
||
MOVEM.L A0-A1/D0-D1,-(SP)
|
||
|
||
Move.L RGB1(A6),A0 ; get first RGBColor
|
||
Move.L RGB2(A6),A1 ; get second RGBColor
|
||
|
||
Move (A1)+,D0 ; grab index red
|
||
Sub (A0)+,D0 ; subtract entry red
|
||
Bhs.S NotNeg1 ; take abs(Index.Red-ColorInfo.Red)
|
||
Neg D0 ; negate it
|
||
NotNeg1 Move (A1)+,D1 ; grab index green
|
||
Sub (A0)+,D1 ; subtract entry green
|
||
Bhs.S NotNeg2 ; take abs(Index.Green-ColorInfo.Green)
|
||
Neg D1 ; negate it
|
||
NotNeg2 Cmp D0,D1 ; leave greater unsigned value in D0
|
||
Blo.S DontSwitch1 ; D1 < D0 => D0 is already greater
|
||
Move D1,D0 ; green value is greater
|
||
DontSwitch1 Move (A1),D1 ; grab index blue
|
||
Sub (A0),D1 ; subtract entry blue
|
||
Bhs.S NotNeg3 ; take abs(Index.Blue-ColorInfo.Blue)
|
||
Neg D1 ; negate it
|
||
NotNeg3 Cmp D0,D1 ; leave greater unsigned value in D0
|
||
Blo.S FixResult ; D1 < D0 => D0 is already greater
|
||
Move D1,D0 ; blue value is greater
|
||
FixResult Move D0,Delta(A6) ; set result
|
||
MOVEM.L (SP)+,A0-A1/D0-D1
|
||
Unlk A6 ; clear stack frame
|
||
Rtd #ParamSize ; strip parameters and go home
|
||
|
||
ENDF
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; FUNCTION myGetCTable(ID:INTEGER):Handle;
|
||
;
|
||
; Get a 'clut' resource of the specified ID, as a non-resource
|
||
; handle. Unless, of course, the number is 32+[1,2,4,8] in which
|
||
; case we return a gray scale of that size. Or if the number is
|
||
; 64+[1,2,4,8] we'll return a clut with a hilite modification.
|
||
;
|
||
; Passing 64 plus other than 1, 2, 4, or 8 will yield strange results.
|
||
;
|
||
; stack like this: (SP) return.L, 4(SP) depth.W, 6(SP) result handle.L
|
||
;
|
||
; <dvb8> for whole routine
|
||
|
||
PROC
|
||
EXPORT GetCTable
|
||
|
||
GrayMuls DC.W $FFFF,$5555,$0000,$1111,$0000,$0000,$0000,$0101 ; <BAL 06Jun89>
|
||
; gray multiplier 1-bit 2-bit 4-bit 8-bit
|
||
|
||
doGrayClut AND #$F,D0 ; Mask the graybit
|
||
MOVE D0,4(SP) ; Put it in the passed param
|
||
CLR.L D1
|
||
ADDQ #3,D0 ; + 3 becomes * 8 on next line, for c-Spec size
|
||
BSET D0,D1 ; 2 to the nth
|
||
ADDQ.L #8,D1 ; Add size of ctab header
|
||
MOVE.L D1,D0 ; Here, for newhandle
|
||
_NewHandle ; Get a brand new colortable
|
||
BEQ.S @gotGrayH ; Did we?
|
||
|
||
CLR.L 6(SP) ; No=>return nil
|
||
RTD #2
|
||
|
||
@gotGrayH MOVE 4(SP),D0 ; Get depth again
|
||
LEA GrayMuls-2,A1 ; A1->our gray multiplier table <2.1>
|
||
MOVE.w (A1,D0*2),D1 ; D1.w = color step for this bit depth <BAL 06Jun89>
|
||
move.w d1,d2 ; copy into d2 <BAL 06Jun89>
|
||
swap d2 ; set up high word <BAL 06Jun89>
|
||
move.w d1,d2 ; replicate throughout long <BAL 06Jun89>
|
||
MOVE.L (A0),A1 ; A1->our brand new ctable clut
|
||
move.w #$8000,transIndex(A1) ; mark as device clut
|
||
CLR D1 ; From bit depth,
|
||
BSET D0,D1 ; Generate number of entries
|
||
SUBQ #1,D1 ; Minus one, for ctSize silliness
|
||
MOVE D1,ctSize(A1) ; Set size of colortable
|
||
CMPI #3,D0 ; Size 1 or 2 bits? <dvb>
|
||
BLT.S @graySeed ; Yes => don't call it GrayScale by seed <dvb>
|
||
ADD #32,D0 ; Constant +32 for GrayScale seeds
|
||
@graySeed MOVE.L D0,ctSeed(A1) ; Jam seed <dvb>
|
||
LEA ctTable(A1),A1 ; A1->first colorSpec
|
||
MOVEQ #-1,D0 ; Lowest index is white
|
||
MOVEQ #0,D1 ; D1 will be .value fields <dvb>
|
||
@grayLoop MOVE D1,(A1)+ ; put pixel value in .value field <dvb>
|
||
ADDQ #1,D1 ; <dvb>
|
||
MOVE.L D0,(A1)+ ; Stash red and green
|
||
MOVE D0,(A1)+ ; Stash blue, A1->next cSpec
|
||
SUB.L D2,D0 ; Bump D0 to next reasonable value
|
||
BCC.S @grayLoop ; Until we go under zero, beyond black
|
||
BRA GoHome
|
||
|
||
doHiliteClut AND #$F,D0 ; Mask the hilitebit
|
||
MOVE D0,-(SP) ; Push it for the Resource read
|
||
BSR ReadIt ; Okay, read it.
|
||
MOVE.L A0,D0 ; A good thing?
|
||
BEQ GoHome ; No=>go home (with NIL from A0)
|
||
MOVE.L (A0),A1 ; A1->color table
|
||
SUBQ #4,SP ; Space for new seed
|
||
_GetCTSeed ; Get that new seed
|
||
MOVE.L (SP)+,ctSeed(A1) ; Put seed into synthetic table
|
||
MOVE 4(SP),D0 ; D0 = clutID again
|
||
BTST #1,D0 ; Two bit mode?
|
||
BEQ.S checkFour ; No=>check other stuff
|
||
|
||
; If the hilite color is a gray then CLUT is OK <2.2>
|
||
LEA HiliteRGB,A1 ; Point at hilite color <2.2>
|
||
MOVE.B red(A1),D1 ; Get red msb <2.2>
|
||
CMP.B green(A1),D1 ; green same as red? <2.2>
|
||
BNE.S @notGray ; no, go use it. <2.2>
|
||
CMP.B blue(A1),D1 ; blue same as red and green? <2.2>
|
||
BEQ GoHome ; yes, leave clut alone. <2.2>
|
||
|
||
@notGray MOVE.L (A0),A1 ; A1->color table <2.2>
|
||
LEA ctTable+8+rgb(A1),A1 ; Bump A1 to 2nd entry.rgb.red
|
||
MOVE.L #$7FFF7FFF,(A1)+ ; Put 50% gray into red,green
|
||
MOVE #$7FFF,(A1)+ ; and blue
|
||
ADDQ #2,A1 ; Bump past .value field in third entry
|
||
MOVE.L HiliteRGB,(A1)+ ; Put hilite color into red,green
|
||
MOVE HiliteRGB+blue,(A1) ; and blue.
|
||
BRA GoHome
|
||
|
||
checkFour BTST #2,D0 ; Four bit mode?
|
||
BEQ GoHome ; No => must be 1 or 8-bit, so we're done.
|
||
|
||
MOVE #14,D2 ; DBRA counter, skipping white
|
||
MOVE.L #$0001FFFF,D1 ; Lo word = error distance, Hi word = best index
|
||
@B4loop SUBQ #2,SP ; space for result
|
||
PEA HiliteRGB ; push system hilite color
|
||
PEA ctTable+rgb(A1,D2*8) ; push color we're checking
|
||
JSR DeltaRGB
|
||
MOVE (SP)+,D0
|
||
CMP D0,D1
|
||
BLS.S @B4loopEnd
|
||
MOVE D0,D1 ; Get new smallest delta
|
||
SWAP D1 ; D1 = Get index number in low word
|
||
MOVE D2,D1 ; Get new closest index
|
||
SWAP D1 ; D1 = Put delta back to low word
|
||
@B4loopEnd SUBQ #1,D2
|
||
BNE.S @B4loop ; Loop on down, but skip zero
|
||
CMPI #$3000,D1 ; Are we pretty darned tolerant?
|
||
BLS.S GoHome ; Yes=> we're fine, go home
|
||
|
||
SWAP D1
|
||
LEA ctTable+rgb+red(A1,D1*8),A1 ; A1->RGB to tweak
|
||
@realClose MOVE.L HiliteRGB+red,D0 ; D0 = hilite r,g
|
||
SWAP D0 ; D0.W = red
|
||
ADD red(A1),D0 ; D0.W = hilite red+old red
|
||
ROXR #1,D0 ; Average
|
||
MOVE D0,red(A1) ; write red
|
||
SWAP D0
|
||
ADD green(A1),D0 ; D0.W = hilite green+old green
|
||
ROXR #1,D0 ; Average
|
||
MOVE D0,green(A1) ; write green
|
||
MOVE HiliteRGB+blue,D0 ; D0.W = hilite blue
|
||
ADD blue(A1),D0
|
||
ROXR #1,D0 ; Average
|
||
MOVE D0,blue(A1) ; write blue
|
||
SUBQ #2,SP ; space for result
|
||
PEA HiliteRGB ; Have we really got the hilite
|
||
PEA (A1) ; color within a reasonable range?
|
||
JSR DeltaRGB ; Let's see.
|
||
CMPI #$3000,(SP)+ ; 3000 is good enough to look decent.
|
||
BHI.S @realClose ; But, its not there yet, so avg again.
|
||
BRA.S GoHome
|
||
|
||
GetCTable clr.l 6(sp) ; NIL return if call fails. <KON 6NOV90>
|
||
MOVE 4(SP),-(SP) ; First, try to read a resource
|
||
BSR.S ReadIt ; (do that)
|
||
MOVE.L A0,D0 ; Get anything?
|
||
BEQ.S notRes ; No=>try other means
|
||
GoHome MOVE.L A0,6(SP) ; Yes=>stash it
|
||
RTD2 RTD #2 ; roger and out.
|
||
|
||
notRes MOVE 4(SP),D0 ; Get requested ID
|
||
CMPI #72,D0 ; 72 is the highest we can noodle
|
||
BHI.S RTD2
|
||
MOVE.L #$00000116,D1 ; Bits 1, 2, 4, and 8 are set
|
||
BTST D0,D1 ; Are low 5 bits in [1,2,4,8]?
|
||
BEQ.S RTD2
|
||
BTST #5,D0
|
||
BNE.S doGrayClut ; 32+[1,2,4,8]
|
||
BTST #6,D0
|
||
BNE.S doHiliteClut ; 64+[1,2,4,8]
|
||
BRA.S RTD2
|
||
|
||
|
||
readIt SUBQ #4,A7 ; space for result
|
||
MOVE.L #'clut',-(SP) ; resource type
|
||
MOVE 12(SP),-(SP) ; push ID number
|
||
_GetResource ; Get it.
|
||
MOVE.L (SP)+,D0 ; Did we get the resource?
|
||
BEQ.S @otherThing
|
||
|
||
MOVE.L D0,-(SP) ; Push the Resource Handle
|
||
MOVE.L D0,-(SP) ; Push the Resource Handle
|
||
_DetachResource ; Free it from the Map
|
||
MOVE.L (SP)+,A0
|
||
_HNoPurge
|
||
|
||
MOVE.L (A0),A1
|
||
SUBQ #4,SP
|
||
_rGetCTSeed
|
||
MOVE.L (SP)+,(A1)
|
||
|
||
BRA.S @Done ; -> Got It!
|
||
|
||
@otherThing
|
||
MOVE #$FFFF,RomMapInsert
|
||
SUBQ #4,SP
|
||
MOVE.L #'clut',-(SP)
|
||
MOVE 12(SP),-(SP)
|
||
_GetResource
|
||
MOVE.L (SP)+,D0
|
||
BEQ.S @readFail
|
||
|
||
MOVE.L D0,A0
|
||
_HandToHand
|
||
BEQ.S @done
|
||
|
||
@readFail SUBA.L A0,A0 ; A miserable failure.
|
||
@done RTD #2 ; Lose ID, and go home.
|
||
|
||
|