Source/Misc.c

/****************************/
/*      MISC ROUTINES       */
/* By Brian Greenstone      */
/****************************/
 
 
/***************/
/* EXTERNALS   */
/***************/
#include <Events.h>
#include <Dialogs.h>
#include <Processes.h>
#include <NumberFormatting.h>
 
#include <QD3D.h>
#include <QD3DErrors.h>
 
#include <timer.h>
#include <math.h>
 
#include "myglobals.h"
#include "misc.h"
#include "main.h"
 
 
/****************************/
/*    CONSTANTS             */
/****************************/
 
#define     ERROR_ALERT_ID      401
 
/**********************/
/*     VARIABLES      */
/**********************/
 
KeyMap gKeyMap,gOldKeyMap;
 
unsigned long   gTick = 0;
 
 
unsigned long seed0 = 0, seed1 = 0, seed2 = 0;
 
/****************** DO SYSTEM ERROR ***************/
 
void ShowSystemErr(long err)
{
Str255      numStr;
 
    NumToString(err, numStr);
    DoAlert (numStr);
    CleanQuit();
}
 
/*********************** DO ALERT *******************/
 
void DoAlert(Str255 s)
{
    ParamText(s,NIL_STRING,NIL_STRING,NIL_STRING);
    NoteAlert(ERROR_ALERT_ID,NIL_POINTER);
}
        
/*********************** DO FATAL ALERT *******************/
 
void DoFatalAlert(Str255 s)
{
    ParamText(s,NIL_STRING,NIL_STRING,NIL_STRING);
    NoteAlert(ERROR_ALERT_ID,NIL_POINTER);
    CleanQuit();
}
 
/************ CLEAN QUIT ***************/
 
void CleanQuit(void)
{
    ExitToShell();
}
 
/********************** WAIT **********************/
 
void Wait(long ticks)
{
long    start;
    
    start = TickCount();
 
    while ((TickCount()-start) < ticks)
        ; 
 
}
 
/**************************** LOAD A FILE *******************/
 
Handle  LoadAFile(Str255 fileName, short volumeRefNum, long *fileSize)
{
OSErr       iErr;
short       fRefNum;
Handle      fileHandle;
 
                    /*  OPEN THE FILE */
                
    iErr = FSOpen(fileName,volumeRefNum,&fRefNum);          // open file                
    if (iErr != noErr)
        DoFatalAlert("\pCant Open File!");
                            
                    /* GET MEMORY FOR FILE */
                        
    if  (GetEOF(fRefNum,fileSize) != noErr)         // get size of text file
        DoFatalAlert("\pError reading File!");
 
    if ((fileHandle = NewHandle(*fileSize)) == NIL_POINTER)
        DoFatalAlert ("\pNo Memory for File!");
    HLock(fileHandle);
 
                    /*  READ THE DATA */
                
    iErr = FSRead(fRefNum,fileSize,*fileHandle);
    if (iErr != noErr)
        DoFatalAlert ("\pError Reading File!");
        
                    /*  CLOSE THE FILE */
                
    iErr = FSClose(fRefNum);
    if (iErr != noErr)
        DoFatalAlert ("\pCant close file!");
    
    return (fileHandle);    
}
 
/***************** NUM TO HEX *****************/
//
// NumToHex - fixed length, returns a C string
//
 
unsigned char *NumToHex(unsigned short n)
{
static unsigned char format[] = "0xXXXX";               // Declare format static so we can return a pointer to it.
char *conv = "0123456789ABCDEF";
short i;
 
    for (i = 0; i < 4; n >>= 4, ++i)
            format[5 - i] = conv[n & 0xf];
    return format;
}
 
 
/***************** NUM TO HEX 2 **************/
//
// NumToHex2 -- allows variable length, returns a ++PASCAL++ string.
//
 
unsigned char *NumToHex2(unsigned long n, short digits)
{
static unsigned char format[] = "\p$XXXXXXXX";              // Declare format static so we can return a pointer to it
char *conv = "0123456789ABCDEF";
unsigned long i;
 
    if (digits > 8 || digits < 0)
            digits = 8;
    format[0] = digits + 1;                         // adjust length byte of output string
 
    for (i = 0; i < digits; n >>= 4, ++i)
            format[(digits + 1) - i] = conv[n & 0xf];
    return format;
}
 
 
/*************** NUM TO DECIMAL *****************/
//
// NumToDecimal --  returns a ++PASCAL++ string.
//
 
unsigned char *NumToDec(unsigned long n)
{
static unsigned char format[] = "\pXXXXXXXX";               // Declare format static so we can return a pointer to it
char *conv = "0123456789";
short        i,digits;
unsigned long temp;
 
    if (n < 10)                                     // fix digits
        digits = 1;
    else if (n < 100)
        digits = 2;
    else if (n < 1000)
        digits = 3;
    else if (n < 10000)
        digits = 4;
    else if (n < 100000)
        digits = 5;
    else
        digits = 6;
 
    format[0] = digits;                             // adjust length byte of output string
 
    for (i = 0; i < digits; ++i)
    {
        temp = n/10;
        format[digits-i] = conv[n-(temp*10)];
        n = n/10;
    }
    return format;
}
 
 
 
/*************** ABSOLUTE ********************/
 
float Absolute(float f)
{
    if (f < 0)
        return(-f);
    else
        return(f);
}
 
/******************** REGULATE SPEED  ***************/
 
void RegulateSpeed(long speed)
{
    while ((TickCount() - gTick) < speed)               // wait for 1 tick
        ;
    gTick = TickCount();                            // remember current time
}
 
/******************** MY RANDOM LONG **********************/
//
// My own random number generator that returns a LONG
//
// NOTE: call this instead of MyRandomShort if the value is going to be
//      masked or if it just doesnt matter since this version is quicker
//      without the 0xffff at the end.
//
 
unsigned long MyRandomLong(void)
{
  return seed2 ^= (((seed1 ^= (seed2>>5)*1568397607UL)>>7)+
                   (seed0 = (seed0+1)*3141592621UL))*2435386481UL;
}
 
 
/**************** SET MY RANDOM SEED *******************/
 
void SetMyRandomSeed(unsigned long seed)
{
    seed0 = seed;
    seed1 = 0;
    seed2 = 0;  
}
 
/************************* RANDOM RANGE *************************/
 
unsigned short  RandomRange(unsigned short min, unsigned short max)
{
register    unsigned short      qdRdm;                          // treat return value as 0-65536
register    unsigned long       range, t;
 
    qdRdm = MyRandomLong()&0xffff;
    range = max+1 - min;
    t = (qdRdm * range)>>16;                                // now 0 <= t <= range
    
    return( t+min );
}
 
 
 
 
/******************* FLOAT TO STRING *******************/
 
void FloatToString(float num, Str255 string)
{
Str255  sf;
long    i,f;
 
    i = num;                        // get integer part
    
    
    f = (fabs(num)-fabs((float)i)) * 10000;     // reduce num to fraction only & move decimal --> 5 places  
 
    if ((i==0) && (num < 0))        // special case if (-), but integer is 0
    {
        string[0] = 2;
        string[1] = '-';
        string[2] = '0';
    }
    else
        NumToString(i,string);      // make integer into string
        
    NumToString(f,sf);              // make fraction into string
    
    string[++string[0]] = '.';      // add "." into string
    
    if (f >= 1)
    {
        if (f < 1000)
            string[++string[0]] = '0';  // add 1000's zero
        if (f < 100)
            string[++string[0]] = '0';  // add 100's zero
        if (f < 10)
            string[++string[0]] = '0';  // add 10's zero
    }
    
    for (i = 0; i < sf[0]; i++)
    {
        string[++string[0]] = sf[i+1];  // copy fraction into string
    }
}
 
/****************** ALLOC HANDLE ********************/
 
Handle  AllocHandle(long size)
{
Handle  hand;
OSErr   err;
 
    hand = NewHandle(size);                         // alloc in APPL
    if (hand == nil)
    {
        hand = TempNewHandle(size,&err);            // try TEMP mem
        if (hand == nil)
        {
            return(NewHandleSys(size));         // use SYS      
        }
        else
            return(hand);                           // use TEMP
    }
    else
        return(hand);                               // use APPL
}
 
 
/****************** ALLOC PTR ********************/
 
Ptr AllocPtr(long size)
{
Ptr pr;
 
    pr = NewPtr(size);                      // alloc in APPL
    if (pr == nil)
    {
        return(NewPtrSys(size));            // alloc in SYS
    }
    else
        return(pr);
}
 
 
/***************** ANGLE TO VECTOR ******************/
//
// Returns a normalized 2D vector based on a radian angle
//
 
void AngleToVector(float angle, TQ3Vector2D *theVector)
{
    theVector->x = -sin(angle);
    theVector->y = -cos(angle);
}
 
 
/************************** VECTORS ARE CLOSE ENOUGH ****************************/
 
Boolean VectorsAreCloseEnough(TQ3Vector3D *v1, TQ3Vector3D *v2)
{
    if (fabs(v1->x - v2->x) < 0.04)
        if (fabs(v1->y - v2->y) < 0.04)
            if (fabs(v1->z - v2->z) < 0.04)
                return(true);
 
    return(false);
}
 
/************************** POINTS ARE CLOSE ENOUGH ****************************/
 
Boolean PointsAreCloseEnough(TQ3Point3D *v1, TQ3Point3D *v2)
{
    if (fabs(v1->x - v2->x) < 0.04)
        if (fabs(v1->y - v2->y) < 0.04)
            if (fabs(v1->z - v2->z) < 0.04)
                return(true);
 
    return(false);
}
 
/************************** UVS ARE CLOSE ENOUGH ****************************/
 
Boolean UVsAreCloseEnough(TQ3Param2D *v1, TQ3Param2D *v2)
{
    if (fabs(v1->u - v2->u) < 0.01)
        if (fabs(v1->v - v2->v) < 0.01)
            return(true);
 
    return(false);
}
 
 
/************* COPY PSTR **********************/
 
void CopyPStr(ConstStr255Param  inSourceStr, StringPtr  outDestStr)
{
short   dataLen = inSourceStr[0] + 1;
    
    BlockMoveData(inSourceStr, outDestStr, dataLen);
    outDestStr[0] = dataLen - 1;
}