/* Hacks to match MacOS (most recent first): 8/3/92 Reverted the fix. 9/2/94 SuperMario ROM source dump (header preserved below) */ /* File: GestaltLookup.c Contains: Gestalt data structure manipulation routines. Written by: Carl C. Hewitt Copyright: © 1988-1990, 1992-1993 by Apple Computer, Inc., all rights reserved. Change History (most recent first): 11/10/93 fau Removed ulong typedef since it's now in Types.h. 5/18/93 RC perfomance/bug fix changed a > to >> in FindLong 4/8/93 CSS Use GestaltPrivateEqu.h, and remove definitions in this file. <11> 10/28/92 DTY Use Get/Set macros to access ExpandMem. <10> 12/13/90 SAM Making Gestalt check for a nil proc ptr on _NewGestalt calls. <9> 8/8/90 CCH Now only uses the stripped address during the check for function location. <8> 8/1/90 SAM NewGestalt now calls stripAddress with the ProcPtr passed to it before checking to see if it is in the sys heap. <7> 7/17/90 dba get rid of MemUtils.h <6> 7/10/90 dba add prototypes <5> 7/7/90 dba change routine names to match Interface.o <4> 1/16/90 cch Fixed unitialized variable in newGestalt. <3> 1/15/90 CCH Fixed routine to add Gestalt selectors to allow Gestalt to be called when interrupts are off. <2> 1/3/90 CCH Changed Gestalt equate file name. <1> 1/2/90 CCH Changed name from Gestalt.c. <1.9> 7/16/89 CCH Changes: (NEEDED FOR 6.0.4 AND AURORA) - Removed unnecessary Hlocks and HUnlocks. <1.8> 7/14/89 CCH Changes: (NEEDED FOR 6.0.4 AND AURORA AND ESPRIT) - Fixed bug in check for gestalt function location. <1.7> 7/10/89 CCH Changes: (NEEDED FOR AURORA) - Added check to make sure new gestalt functions are in the sys heap. <1.6> 5/25/89 CCH Added new parameter to getGestalt function to allow it pass back old values when replacing codes. <1.5> 5/18/89 CCH Several changes to Gestalt: - rewrote getGestalt in assembly and moved to Gestalt.a - changed prefix to Gestalt equates to "gestalt" - changed to new error codes <1.4> 4/16/89 CCH Changed equates to new naming convention. <1.3> 4/13/89 CCH Gestalt now passes through the return values of function code routines. <1.2> 3/30/89 CCH Optimized everything. <1.1> 3/2/89 CCH Moved init code to GestaltInit.c, and cleaned up some stuff. <1.0> 2/21/89 CCH Adding to EASE for the first time. */ /********************************************************************************* * * File: Gestalt.c * * Data structure access routines for Gestalt. * * By Carl C. Hewitt * November 30th, 1988 * * © Copyright 1988-1989 Apple Computer, Inc. * *********************************************************************************/ #include #include #include #include #include #include #include /************************ * types local to this file ************************/ typedef ulong LongEntry[2]; /* long entry */ typedef LongEntry *LongEntryPtr; /* ptr to a long entry */ typedef ulong (*FuncPtr)(); /* ptr to a function that returns a long */ #define GestaltPtr ((GestaltGlobalsPtr) (GetExpandMemGestalt())) /************************ * prototypes ************************/ OSErr newGestalt(ulong replace, ulong selector, ulong value, ulong *oldProc); OSErr removeLong(ulong selector, ulong* oldValue); OSErr findLong(ulong selector, int* index); /********************************************************************************* * function: newGestalt(replace, selector, value, oldProc) * ulong selector; * ulong value; * int replace; * ulong *oldProc; * purpose: adds the specified long into the table as entry #selector, or changes * it if it already exists. replace determines whether this is an add or * replace function. true means replace, false means add * * Replace Exists Error Action * ——————— —————— ————— —————— * false false no add * false true yes - * true false yes - * true true no replace * * lastmod: 1/15/90 *********************************************************************************/ OSErr newGestalt(ulong replace, ulong selector, ulong value, ulong *oldProc) { LongEntryPtr tablePtr; Handle tempTable, myHandle; int i, index, found; ulong *destPtr, *srcPtr, size, strippedVal; OSErr myResult; if (!(value) || (value & 1)) /* proc ptr must be even */ return(paramErr); /** Make sure the gestalt function is in the System Heap <1.7> **/ strippedVal = StripAddress((Ptr)value); /* gotta lose them high bits... <8><9> */ if ((strippedVal > **(ulong**)SysZone) && (strippedVal < StripAddress(*(Ptr*)ROMBase))) return(gestaltLocationErr); /** Make a new table to make our changes to so we can use Gestalt from **/ /** interrupt routines **/ size = GetHandleSize( GestaltPtr->tableH ); /* get the size of the table */ tempTable = NewHandleSysClear( size ); if (*(short*)MemErr) /* was there a problem? */ return(memFullErr); destPtr = (ulong*) *tempTable; /* get a pointer to the new table */ srcPtr = (ulong*) *GestaltPtr->tableH; /* get a pointer to the orginal one */ for (i=0; islotsUsed + 1) * sizeof(LongEntry)); if (*(short*)MemErr) /* was there a problem? */ myResult = memFullErr; else found = false; } } else if (!replace) /* trying to add an existing selector? */ myResult = gestaltDupSelectorErr; if (myResult != noErr) /* any errors? */ { DisposHandle(tempTable); /* get rid of our temporary table */ return(myResult); } /** index now contains the index that the entry should be put in at, **/ /** so increase the table size by one entry, and shift everything above **/ /** index up by one entry. **/ tablePtr = (LongEntryPtr) *tempTable; if (!found) /* if not in table, add it */ { for (i=GestaltPtr->slotsUsed; i > index; i--) /* shift entries up by one */ { tablePtr[i][0] = tablePtr[i-1][0]; tablePtr[i][1] = tablePtr[i-1][1]; } GestaltPtr->slotsUsed++; /* there is now one more entry */ tablePtr[index][0] = selector; /* add the entry information */ } if (replace) /* if replacing, save old value */ *oldProc = tablePtr[index][1]; tablePtr[index][1] = value; /* associate this value with the selector */ /** Swap the tables that are used during a lookup. **/ myHandle = GestaltPtr->tableH; GestaltPtr->tableH = tempTable; DisposHandle(myHandle); return(noErr); } /*newGestalt*/ /********************************************************************************* * function: removeLong(selector, oldValue) * ulong selector; * ulong *oldValue; * purpose: removes the specified long from the table, and returns the old * value. * lastmod: 7/15/89 *********************************************************************************/ OSErr removeLong(ulong selector, ulong* oldValue) { int index, i; LongEntryPtr tablePtr; if (!findLong(selector, &index)) /* the selector has to exist to delete it! */ return(gestaltUndefSelectorErr); /** index now contains the index of the entry should be deleted **/ /** so decrease the table size by one entry, and shift everything above **/ /** index down by one entry. **/ tablePtr = (LongEntryPtr) *GestaltPtr->tableH; *oldValue = tablePtr[index][1]; /* get the old value */ for (i=index; i < (GestaltPtr->slotsUsed-1); i++) { /* shift entries down by one */ tablePtr[i][0] = tablePtr[i+1][0]; tablePtr[i][1] = tablePtr[i+1][1]; } /*for*/ GestaltPtr->slotsUsed--; /* there is now one less entry */ SetHandleSize(GestaltPtr->tableH, GestaltPtr->slotsUsed * sizeof(LongEntry)); return(noErr); } /*removeLong*/ /********************************************************************************* * function: findLong(selector, index) * ulong selector; * int *index; * purpose: returns true if the specified entry is in the table, false other- * wise. If true is returned, index contains the index of the entry, * otherwise, index will contain the index where the entry should be * added. * lastmod: 7/15/89 *********************************************************************************/ OSErr findLong(ulong selector, int* index) { int i, min, max; LongEntryPtr tablePtr; tablePtr = (LongEntryPtr) *GestaltPtr->tableH; /** do a binary search on the table for the selector **/ min = 0; max = GestaltPtr->slotsUsed-1; do { i = min + ((max - min) > 1); /* get middle of range ex */ if (tablePtr[i][0] > selector) /* are we too high? (is that possible?) */ max = i; else if (tablePtr[i][0] < selector) /* are we too low? */ min = i+1; else { *index = i; /* we got it! */ return(true); } } while (max != min); /* until we know it's not there */ *index = min; return(false); } /*findLong*/