mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
2700 lines
105 KiB
Plaintext
2700 lines
105 KiB
Plaintext
;
|
|
; File: ColorMgr.a
|
|
;
|
|
; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM9> 11/29/93 SAM Yet another getCTable mod. Move the handle to the clut copy
|
|
; into A0 prior to the seed range check.
|
|
; <SM8> 11/7/93 SAM Changed GetCTable to get a new seed if the id > 1023 (kMinSeed).
|
|
; <SM7> 9/29/93 SAM From mc900ftjesus
|
|
; <MC4> 9/27/93 SAM Rewrote the guts of GetCTable. The result of calling GetCtable
|
|
; is a Handle to a ram based copy of the clut (whether its in ROM
|
|
; or not). It no longer requires that you have 2x sixeof(clut)
|
|
; heap space. Made GetCTable not set ctSeed if the ct ID is ² 8.
|
|
; <SM6> 9/13/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
|
|
; so they can conditionalized out of the build.
|
|
; <SM5> 3/3/93 PN Fix the rGetResource in MakeITable by adjusting the CurMap to
|
|
; point to SysMap before calling rGetResource. Roll in patch
|
|
; StartRGetResourceFromSystemMapFormitqResources
|
|
; <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>
|
|
|
|
; Here is the fix for rGetResource from ResourceMgrPatches.a
|
|
move.w CurMap,-(sp) ; Save the current resource map. <SM5>
|
|
move.w SysMap,CurMap ; <27> Start searching from the System file instead of the top <SM5>
|
|
|
|
; 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.w (sp)+,CurMap ; Restore the current resource map <SM5>
|
|
|
|
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 MOVEM.L D6/D7,-(SP) ; Save some work registers <SAM 27SEP93>
|
|
MOVE.W #mapTrue,ROMMapInsert ; Put the ROM map at the lend of the list
|
|
SUBQ #4,A7 ; space for result
|
|
MOVE.L #'clut',-(SP) ; resource type
|
|
MOVE 20(SP),-(SP) ; push ID number
|
|
_GetResource ; Get it.
|
|
MOVE.L (SP)+,D7 ; Did we get the resource?
|
|
BEQ.S @readFail ; -> Nope, Clear A0 and exit.
|
|
|
|
MOVE.L D7,-(SP) ; Push the Resource Handle
|
|
_DetachResource ; Free it from the Map
|
|
|
|
MOVE.L D7,D6 ; Put the orig in D6
|
|
MOVE.L D7,A0 ; Get the handle in A0
|
|
MOVE.L D7,A1 ; Get the handle in A1
|
|
|
|
MOVE.L (A1),A1 ; Get the ptr
|
|
CMP.L ROMBase,A1 ; Is the clut in ROM?
|
|
BLO.S @SetTheSeed ; -> No. Its in RAM. Set the seed and leave
|
|
|
|
_HandToHand ; Make a copy in a new handle in RAM
|
|
MOVE.L A0,D6 ; Save the copy in D6
|
|
|
|
MOVE.L D7,A0 ; Get the resource handle in A0
|
|
_DisposHandle ; Free the ROM handle
|
|
|
|
MOVE.L D6,A0 ; Move the copy into A0 <SM9>
|
|
TST.L D6 ; Did we get the copy?
|
|
BEQ.S @ReadFail ; -> No. Clear A0 and exit
|
|
|
|
@SetTheSeed CMPI.W #1023,18(SP) ; Is this a request for a system clut? <MC4><MC5>
|
|
BLS.S @done ; -> Yes, leave the seed alone! <MC4>
|
|
|
|
CLR.L -(SP) ; make room for function return
|
|
_rGetCTSeed ; get the next seed and leave it on the stack
|
|
MOVE.L D6,A0 ; Get the copy in A0
|
|
MOVE.L (SP)+,([A0],ctSeed) ; Set the Seed in the copy
|
|
|
|
_HNoPurge ; Make sure it doesn't go away
|
|
BRA.S @Done ; -> Got It!
|
|
|
|
@readFail SUBA.L A0,A0 ; A miserable failure.
|
|
@done MOVEM.L (SP)+,D6/D7 ; Restore the work registers
|
|
RTD #2 ; Lose ID, and go home.
|
|
|
|
|