GliderPRO/Sources/Utilities.c
John Calhoun 7a70d18ba6 First check-in.
Sources for Glider PRO, a Macintosh game written by John Calhoun and
published by Casady & Greene, Inc. I believe it was using CodeWarrior
IDE to create a fat (68K and PowerPC) binary.
2016-01-28 08:10:38 -08:00

1 line
19 KiB
C
Executable File

//============================================================================
//----------------------------------------------------------------------------
// Utilities.c
//----------------------------------------------------------------------------
//============================================================================
#include <Icons.h>
#include <NumberFormatting.h>
#include <Resources.h>
#include <Sound.h>
#include <TextUtils.h>
#include <ToolUtils.h>
#include "Externs.h"
#include "Utilities.h"
GDHandle thisGDevice;
UInt32 theSeed;
extern Boolean switchedOut;
//============================================================== Functions
//-------------------------------------------------------------- MyGetGlobalMouse
// Returns the position of the mouse in global coordinates.
Point MyGetGlobalMouse (void)
{
Point localWhere;
GetMouse(&localWhere);
LocalToGlobal(&localWhere);
return (localWhere);
}
//-------------------------------------------------------------- ToolBoxInit
// The standard ToolBox intialization that must happen when any MacÉ
// program first launches.
void ToolBoxInit (void)
{
#if !TARGET_CARBON
InitGraf(&qd.thePort);
InitFonts();
FlushEvents(everyEvent, 0);
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
MaxApplZone();
MoreMasters();
MoreMasters();
MoreMasters();
MoreMasters();
GetDateTime((UInt32 *)&qd.randSeed);
#endif
InitCursor();
switchedOut = false;
}
//-------------------------------------------------------------- RandomInt
// Returns a random integer (short) within "range".
short RandomInt (short range)
{
register long rawResult;
rawResult = Random();
if (rawResult < 0L)
rawResult *= -1L;
rawResult = (rawResult * (long)range) / 32768L;
return ((short)rawResult);
}
//-------------------------------------------------------------- RandomLong
// Returns a random long interger within "range".
long RandomLong (long range)
{
register long highWord, lowWord;
register long rawResultHi, rawResultLo;
highWord = (range & 0xFFFF0000) >> 16;
lowWord = range & 0x0000FFFF;
rawResultHi = Random();
if (rawResultHi < 0L)
rawResultHi *= -1L;
rawResultHi = (rawResultHi * highWord) / 32768L;
rawResultLo = Random();
if (rawResultLo < 0L)
rawResultLo *= -1L;
rawResultLo = (rawResultLo * lowWord) / 32768L;
rawResultHi = (rawResultHi << 16) + rawResultLo;
return (rawResultHi);
}
//-------------------------------------------------------------- InitRandomLongQUS
// Initializes random seed for quick & dirty long random number function (below).
void InitRandomLongQUS (void)
{
GetDateTime(&theSeed);
}
//-------------------------------------------------------------- RandomLongQUS
// Very simple (but fast) pseudo-random number generator.
UInt32 RandomLongQUS (void)
{
theSeed = theSeed * 1103515245 + 12345;
return (theSeed);
}
//-------------------------------------------------------------- RedAlert
// Called when we must quit app. Brings up a dialog informing userÉ
// of the problem and the exits to shell.
void RedAlert (short errorNumber)
{
#define rDeathAlertID 170 // alert res. ID for death error
#define rErrTitleID 170 // string ID for death error title
#define rErrMssgID 171 // string ID for death error message
short dummyInt;
Str255 errTitle, errMessage, errNumberString;
InitCursor();
if (errorNumber > 1) // <= 0 is unaccounted for
{
GetIndString(errTitle, rErrTitleID, errorNumber);
GetIndString(errMessage, rErrMssgID, errorNumber);
}
else
{
GetIndString(errTitle, rErrTitleID, 1);
GetIndString(errMessage, rErrMssgID, 1);
}
NumToString((long)errorNumber, errNumberString);
ParamText(errTitle, errMessage, errNumberString, "\p");
// CenterAlert(rDeathAlertID);
dummyInt = Alert(rDeathAlertID, nil);
ExitToShell();
}
//-------------------------------------------------------------- FindOurDevice
// Finds the main device (monitor with the menu bar on it).
void FindOurDevice (void)
{
thisGDevice = GetMainDevice();
if (thisGDevice == nil)
RedAlert(kErrFailedGetDevice);
}
//-------------------------------------------------------------- CreateOffScreenBitMap
// Creates an offscreen bit map (b&w - 1 bit depth).
/*
void CreateOffScreenBitMap (Rect *theRect, GrafPtr *offScreen)
{
GrafPtr theBWPort;
BitMap theBitMap;
long theRowBytes;
theBWPort = (GrafPtr)(NewPtr(sizeof(GrafPort)));
OpenPort(theBWPort);
theRowBytes = (long)((theRect->right - theRect->left + 15L) / 16L) * 2L;
theBitMap.rowBytes = (short)theRowBytes;
theBitMap.baseAddr = NewPtr((long)theBitMap.rowBytes *
(theRect->bottom - theRect->top));
if (theBitMap.baseAddr == nil)
RedAlert(kErrNoMemory);
theBitMap.bounds = *theRect;
if (MemError() != noErr)
RedAlert(kErrNoMemory);
SetPortBits(&theBitMap);
ClipRect(theRect);
RectRgn(theBWPort->visRgn, theRect);
EraseRect(theRect);
*offScreen = theBWPort;
}
*/
//-------------------------------------------------------------- CreateOffScreenPixMap
// Creates an offscreen pix map using the depth of the current device.
/*
void CreateOffScreenPixMap (Rect *theRect, CGrafPtr *offScreen)
{
CTabHandle thisColorTable;
GDHandle oldDevice;
CGrafPtr newCGrafPtr;
Ptr theseBits;
long sizeOfOff, offRowBytes;
OSErr theErr;
short thisDepth;
char wasState;
oldDevice = GetGDevice();
SetGDevice(thisGDevice);
newCGrafPtr = nil;
newCGrafPtr = (CGrafPtr)NewPtr(sizeof(CGrafPort));
if (newCGrafPtr != nil)
{
OpenCPort(newCGrafPtr);
thisDepth = (**(*newCGrafPtr).portPixMap).pixelSize;
offRowBytes = ((((long)thisDepth *
(long)(theRect->right - theRect->left)) + 15L) >> 4L) << 1L;
sizeOfOff = (long)(theRect->bottom - theRect->top + 1) * offRowBytes;
// sizeOfOff = (long)(theRect->bottom - theRect->top) * offRowBytes;
OffsetRect(theRect, -theRect->left, -theRect->top);
theseBits = NewPtr(sizeOfOff);
if (theseBits != nil)
{ // workaround
(**(*newCGrafPtr).portPixMap).baseAddr = theseBits + offRowBytes;
// (**(*newCGrafPtr).portPixMap).baseAddr = theseBits;
(**(*newCGrafPtr).portPixMap).rowBytes = (short)offRowBytes + 0x8000;
(**(*newCGrafPtr).portPixMap).bounds = *theRect;
wasState = HGetState((Handle)thisGDevice);
HLock((Handle)thisGDevice);
thisColorTable = (**(**thisGDevice).gdPMap).pmTable;
HSetState((Handle)thisGDevice, wasState);
theErr = HandToHand((Handle *)&thisColorTable);
(**(*newCGrafPtr).portPixMap).pmTable = thisColorTable;
ClipRect(theRect);
RectRgn(newCGrafPtr->visRgn, theRect);
ForeColor(blackColor);
BackColor(whiteColor);
EraseRect(theRect);
}
else
{
CloseCPort(newCGrafPtr);
DisposePtr((Ptr)newCGrafPtr);
newCGrafPtr = nil;
RedAlert(kErrNoMemory);
}
}
else
RedAlert(kErrNoMemory);
*offScreen = newCGrafPtr;
SetGDevice(oldDevice);
}
*/
//-------------------------------------------------------------------- CreateOffScreenGWorld
// Creates an offscreen GWorldÊusing the depth passed in.
OSErr CreateOffScreenGWorld (GWorldPtr *theGWorld, Rect *bounds, short depth)
{
OSErr theErr;
theErr = NewGWorld(theGWorld, depth, bounds, nil, nil, useTempMem);
if (theErr)
theErr = NewGWorld(theGWorld, depth, bounds, nil, nil, 0);
LockPixels(GetGWorldPixMap(*theGWorld));
return theErr;
}
//-------------------------------------------------------------- KillOffScreenPixMap
// Destroys memory allocated by an offscreen pix map.
/*
void KillOffScreenPixMap (CGrafPtr offScreen)
{
Ptr theseBits;
if (offScreen != nil)
{
theseBits = (**(*offScreen).portPixMap).baseAddr;
theseBits -= (**(*offScreen).portPixMap).rowBytes & 0x7FFF; // workaround
DisposePtr(theseBits);
DisposeHandle((Handle)(**(*offScreen).portPixMap).pmTable);
CloseCPort(offScreen);
DisposePtr((Ptr)offScreen);
}
}
*/
//-------------------------------------------------------------- KillOffScreenBitMap
// Destroys memory allocated by an offscreen bit map.
/*
void KillOffScreenBitMap (GrafPtr offScreen)
{
if (offScreen != nil)
{
DisposePtr((Ptr)(offScreen->portBits.baseAddr));
ClosePort(offScreen);
DisposePtr((Ptr)offScreen);
}
}
*/
//-------------------------------------------------------------- LoadGraphic
// Function loads the specified 'PICT' from disk and draws it toÉ
// the current port (no scaling, clipping, etc, are done). AlwaysÉ
// draws in the upper left corner of current port.
void LoadGraphic (short resID)
{
Rect bounds;
PicHandle thePicture;
thePicture = GetPicture(resID);
if (thePicture == nil)
RedAlert(kErrFailedGraphicLoad);
HLock((Handle)thePicture);
bounds = (*thePicture)->picFrame;
HUnlock((Handle)thePicture);
OffsetRect(&bounds, -bounds.left, -bounds.top);
DrawPicture(thePicture, &bounds);
ReleaseResource((Handle)thePicture);
}
//-------------------------------------------------------------- LoadScaledGraphic
// Loads the specified 'PICT' and draws it mapped to the rectangleÉ
// specified. If this rect isn't the same size of the 'PICT', scalingÉ
// will occur.
void LoadScaledGraphic (short resID, Rect *theRect)
{
PicHandle thePicture;
thePicture = GetPicture(resID);
if (thePicture == nil)
RedAlert(kErrFailedGraphicLoad);
DrawPicture(thePicture, theRect);
ReleaseResource((Handle)thePicture);
}
//-------------------------------------------------------------- PlotSICN
// Draws a small icon (16 x 16 pixels).
/*
void PlotSICN (Rect *theRect, SICNHand theSICN, long theIndex)
{
char state;
BitMap srcBits;
if ((theSICN != nil) &&
((GetHandleSize((Handle)theSICN) / sizeof(SICN)) > theIndex))
{
state = HGetState((Handle)theSICN);
HLock((Handle)theSICN);
srcBits.baseAddr = (Ptr)(*theSICN)[theIndex];
srcBits.rowBytes = 2;
SetRect(&srcBits.bounds, 0, 0, 16, 16);
CopyBits(&srcBits,&(*qd.thePort).portBits,
&srcBits.bounds, theRect, srcCopy, nil);
HSetState((Handle) theSICN, state);
}
}
*/
//-------------------------------------------------------------- LargeIconPlot
// Draws a standard b&w icon (32 x 32) - resource is an 'ICON'.
void LargeIconPlot (Rect *theRect, short theID)
{
OSErr theErr;
Handle theSuite;
theErr = GetIconSuite(&theSuite, theID, svAllLargeData);
if (theErr == noErr)
theErr = PlotIconSuite(theRect, atNone, ttNone, theSuite);
}
//-------------------------------------------------------------- DrawCIcon
// Draws a standard color icon (32 x 32) - resource is a 'CICN'.
void DrawCIcon (short theID, short h, short v)
{
CIconHandle theIcon;
Rect theRect;
theIcon = GetCIcon(theID);
if (theIcon != nil)
{
SetRect(&theRect, 0, 0, 32, 32);
OffsetRect(&theRect, h, v);
PlotCIcon(&theRect, theIcon);
DisposeCIcon(theIcon);
}
}
//-------------------------------------------------------------- LongSquareRoot
// This is a quick and dirty square root function that returns prettyÉ
// accurate long integer results. It uses no transcendental functions orÉ
// floating point.
long LongSquareRoot (long theNumber)
{
long currentAnswer;
long nextTrial;
if (theNumber <= 1L)
return (theNumber);
nextTrial = theNumber / 2;
do
{
currentAnswer = nextTrial;
nextTrial = (nextTrial + theNumber / nextTrial) / 2;
}
while (nextTrial < currentAnswer);
return(currentAnswer);
}
//-------------------------------------------------------------- WaitForInputEvent
// Wait for either a key to be hit or the mouse button to be clicked.
// Also has a "timeout" parameter ("seconds").
Boolean WaitForInputEvent (short seconds)
{
EventRecord theEvent;
KeyMap theKeys;
long timeToBail;
Boolean waiting, didResume;
timeToBail = TickCount() + 60L * (long)seconds;
FlushEvents(everyEvent, 0);
waiting = true;
didResume = false;
while (waiting)
{
GetKeys(theKeys);
if ((BitTst(&theKeys, kCommandKeyMap)) || (BitTst(&theKeys, kOptionKeyMap)) ||
(BitTst(&theKeys, kShiftKeyMap)) || (BitTst(&theKeys, kControlKeyMap)))
waiting = false;
if (GetNextEvent(everyEvent, &theEvent))
{
if ((theEvent.what == mouseDown) || (theEvent.what == keyDown))
waiting = false;
else if ((theEvent.what == osEvt) && (theEvent.message & 0x01000000))
{
if (theEvent.message & 0x00000001) // resuming
{
didResume = true;
waiting = false;
}
else // suspending
{
InitCursor();
}
}
}
if ((seconds != -1) && (TickCount() >= timeToBail))
waiting = false;
}
FlushEvents(everyEvent, 0);
return (didResume);
}
//-------------------------------------------------------------- WaitCommandQReleased
// Waits until the Command-Q key combination is released.
void WaitCommandQReleased (void)
{
KeyMap theKeys;
Boolean waiting;
waiting = true;
while (waiting)
{
GetKeys(theKeys);
if ((!BitTst(&theKeys, kCommandKeyMap)) || (!BitTst(&theKeys, kQKeyMap)))
waiting = false;
}
FlushEvents(everyEvent, 0);
}
//-------------------------------------------------------------- KeyMapOffsetFromRawKey
// Converts a raw key code to keymap offset (ugly stuff).
char KeyMapOffsetFromRawKey (char rawKeyCode)
{
char hiByte, loByte, theOffset;
hiByte = rawKeyCode & 0xF0;
loByte = rawKeyCode & 0x0F;
if (loByte <= 0x07)
theOffset = hiByte + (0x07 - loByte);
else
theOffset = hiByte + (0x17 - loByte);
return (theOffset);
}
//-------------------------------------------------------------- GetKeyMapFromMessage
// Gets the key map offset from a keyDown event's message field.
char GetKeyMapFromMessage (long message)
{
long theVirtual;
char offset;
theVirtual = (message & keyCodeMask) >> 8;
offset = KeyMapOffsetFromRawKey((char)theVirtual);
return (offset);
}
//-------------------------------------------------------------- GetKeyName
// Given a keyDown event (it's message field), this function returnsÉ
// a string with that key's name (so we get "Shift" and "Esc", etc.).
void GetKeyName (long message, StringPtr theName)
{
long theASCII, theVirtual;
theASCII = message & charCodeMask;
theVirtual = (message & keyCodeMask) >> 8;
if ((theASCII >= kExclamationASCII) && (theASCII <= kZKeyASCII))
{
if ((theVirtual >= 0x0041) && (theVirtual <= 0x005C))
{
PasStringCopy("\p( )", theName);
theName[2] = (char)theASCII;
}
else
{
PasStringCopy("\p key", theName);
theName[1] = (char)theASCII;
}
}
else
{
switch (theASCII)
{
case kHomeKeyASCII:
PasStringCopy("\phome", theName);
break;
case kEnterKeyASCII:
PasStringCopy("\penter", theName);
break;
case kEndKeyASCII:
PasStringCopy("\pend", theName);
break;
case kHelpKeyASCII:
PasStringCopy("\phelp", theName);
break;
case kDeleteKeyASCII:
PasStringCopy("\pdelete", theName);
break;
case kTabKeyASCII:
PasStringCopy("\ptab", theName);
break;
case kPageUpKeyASCII:
PasStringCopy("\ppg up", theName);
break;
case kPageDownKeyASCII:
PasStringCopy("\ppg dn", theName);
break;
case kReturnKeyASCII:
PasStringCopy("\preturn", theName);
break;
case kFunctionKeyASCII:
switch (theVirtual)
{
case 0x0060:
PasStringCopy("\pF5", theName);
break;
case 0x0061:
PasStringCopy("\pF6", theName);
break;
case 0x0062:
PasStringCopy("\pF7", theName);
break;
case 0x0063:
PasStringCopy("\pF3", theName);
break;
case 0x0064:
PasStringCopy("\pF8", theName);
break;
case 0x0065:
PasStringCopy("\pF9", theName);
break;
case 0x0067:
PasStringCopy("\pF11", theName);
break;
case 0x0069:
PasStringCopy("\pF13", theName);
break;
case 0x006B:
PasStringCopy("\pF14", theName);
break;
case 0x006D:
PasStringCopy("\pF10", theName);
break;
case 0x006F:
PasStringCopy("\pF12", theName);
break;
case 0x0071:
PasStringCopy("\pF15", theName);
break;
case 0x0076:
PasStringCopy("\pF4", theName);
break;
case 0x0078:
PasStringCopy("\pF2", theName);
break;
case 0x007A:
PasStringCopy("\pF1", theName);
break;
default:
NumToString(theVirtual, theName);
break;
}
break;
case kClearKeyASCII:
PasStringCopy("\pclear", theName);
break;
case kEscapeKeyASCII:
if (theVirtual == 0x0047)
PasStringCopy("\pclear", theName);
else
PasStringCopy("\pesc", theName);
break;
case kLeftArrowKeyASCII:
PasStringCopy("\plf arrow", theName);
break;
case kRightArrowKeyASCII:
PasStringCopy("\prt arrow", theName);
break;
case kUpArrowKeyASCII:
PasStringCopy("\pup arrow", theName);
break;
case kDownArrowKeyASCII:
PasStringCopy("\pdn arrow", theName);
break;
case kSpaceBarASCII:
PasStringCopy("\pspace", theName);
break;
case kForwardDeleteASCII:
PasStringCopy("\pfrwd del", theName);
break;
default:
PasStringCopy("\p????", theName);
break;
}
}
}
//-------------------------------------------------------------- OptionKeyDown
// Returns true is the Option key is being held down.
Boolean OptionKeyDown (void)
{
KeyMap theKeys;
GetKeys(theKeys);
if (BitTst(&theKeys, kOptionKeyMap))
return (true);
else
return (false);
}
//-------------------------------------------------------------- ExtractCTSeed
// Very esoteric - gets the "color table seed" from a specified graf port.
/*
long ExtractCTSeed (CGrafPtr porter)
{
long theSeed;
theSeed = (**((**(porter->portPixMap)).pmTable)).ctSeed;
return(theSeed);
}
*/
//-------------------------------------------------------------- ForceCTSeed
// Forces the "color table seed" from a specified graf port to aÉ
// specified value.
/*
void ForceCTSeed (CGrafPtr porter, long newSeed)
{
(**((**(porter->portPixMap)).pmTable)).ctSeed = newSeed;
}
*/
//-------------------------------------------------------------- DelayTicks
// Lil' function that just sits and waits a specified number ofÉ
// Ticks (1/60 of a second).
void DelayTicks (long howLong)
{
UInt32 whoCares;
Delay(howLong, &whoCares);
}
//-------------------------------------------------------------- UnivGetSoundVolume
// Returns the speaker volume (as set by the user) in the range ofÉ
// zero to seven (handles Sound Manager 3 case as well).
void UnivGetSoundVolume (short *volume, Boolean hasSM3)
{
#pragma unused (hasSM3)
long longVol;
OSErr theErr;
// if (hasSM3)
// {
theErr = GetDefaultOutputVolume(&longVol);
*volume = LoWord(longVol) / 0x0024;
// }
// else
// GetSoundVol(volume);
if (*volume > 7)
*volume = 7;
else if (*volume < 0)
*volume = 0;
}
//-------------------------------------------------------------- UnivSetSoundVolume
// Sets the speaker volume to a specified value (in the range ofÉ
// zero to seven (handles Sound Manager 3 case as well).
void UnivSetSoundVolume (short volume, Boolean hasSM3)
{
#pragma unused (hasSM3)
long longVol;
OSErr theErr;
if (volume > 7)
volume = 7;
else if (volume < 0)
volume = 0;
// if (hasSM3)
// {
longVol = (long)volume * 0x0025;
if (longVol > 0x00000100)
longVol = 0x00000100;
longVol = longVol + (longVol << 16);
theErr = SetDefaultOutputVolume(longVol);
// }
// else
// SetSoundVol(volume);
}