Initial commit.

This commit is contained in:
Jim Gray
2013-04-04 14:32:05 -07:00
parent ba5c81da32
commit d71d53e8ec
2180 changed files with 1393544 additions and 1 deletions

487
code/mac/MacGamma.c Normal file
View File

@@ -0,0 +1,487 @@
/*
File: MacGamma.cpp
Contains: Functions to enable Mac OS device gamma adjustments using Windows common 3 channel 256 element 8 bit gamma ramps
Written by: Geoff Stahl
Copyright: Copyright © 1999 Apple Computer, Inc., All Rights Reserved
Change History (most recent first):
<4> 5/20/99 GGS Added handling for gamma tables with different data widths,
number of entries, and channels. Forced updates to 3 channels
(poss. could break on rare card, but very unlikely). Added
quick update with BlockMove for 3x256x8 tables. Updated function
names.
<3> 5/20/99 GGS Cleaned up and commented
<2> 5/20/99 GGS Added system wide get and restore gamma functions to enable
restoration of original for all devices. Modified functionality
to return pointers vice squirreling away the memory.
<1> 5/20/99 GGS Initial Add
*/
// system includes ----------------------------------------------------------
#include <Devices.h>
#include <Files.h>
#include <MacTypes.h>
#include <QDOffscreen.h>
#include <Quickdraw.h>
#include <video.h>
// project includes ---------------------------------------------------------
#include "MacGamma.h"
// functions (external/public) ----------------------------------------------
// GetRawDeviceGamma
// Returns the device gamma table pointer in ppDeviceTable
OSErr GetGammaTable (GDHandle hGD, GammaTblPtr * ppTableGammaOut)
{
VDGammaRecord DeviceGammaRec;
CntrlParam cParam;
OSErr err;
cParam.ioCompletion = NULL; // set up control params
cParam.ioNamePtr = NULL;
cParam.ioVRefNum = 0;
cParam.ioCRefNum = (**hGD).gdRefNum;
cParam.csCode = cscGetGamma; // Get Gamma commnd to device
*(Ptr *)cParam.csParam = (Ptr) &DeviceGammaRec; // record for gamma
err = PBStatus( (ParmBlkPtr)&cParam, 0 ); // get gamma
*ppTableGammaOut = (GammaTblPtr)(DeviceGammaRec.csGTable); // pull table out of record
return err;
}
// --------------------------------------------------------------------------
// CreateEmptyGammaTable
// creates an empty gamma table of a given size, assume no formula data will be used
Ptr CreateEmptyGammaTable (short channels, short entries, short bits)
{
GammaTblPtr pTableGammaOut = NULL;
short tableSize, dataWidth;
dataWidth = (bits + 7) / 8; // number of bytes per entry
tableSize = sizeof (GammaTbl) + (channels * entries * dataWidth);
pTableGammaOut = (GammaTblPtr) NewPtrClear (tableSize); // allocate new tabel
if (pTableGammaOut) // if we successfully allocated
{
pTableGammaOut->gVersion = 0; // set parameters based on input
pTableGammaOut->gType = 0;
pTableGammaOut->gFormulaSize = 0;
pTableGammaOut->gChanCnt = channels;
pTableGammaOut->gDataCnt = entries;
pTableGammaOut->gDataWidth = bits;
}
return (Ptr)pTableGammaOut; // return whatever we allocated
}
// --------------------------------------------------------------------------
// CopyGammaTable
// given a pointer toa device gamma table properly iterates and copies
Ptr CopyGammaTable (GammaTblPtr pTableGammaIn)
{
GammaTblPtr pTableGammaOut = NULL;
short tableSize, dataWidth;
if (pTableGammaIn) // if there is a table to copy
{
dataWidth = (pTableGammaIn->gDataWidth + 7) / 8; // number of bytes per entry
tableSize = sizeof (GammaTbl) + pTableGammaIn->gFormulaSize +
(pTableGammaIn->gChanCnt * pTableGammaIn->gDataCnt * dataWidth);
pTableGammaOut = (GammaTblPtr) NewPtr (tableSize); // allocate new table
if (pTableGammaOut)
BlockMove( (Ptr)pTableGammaIn, (Ptr)pTableGammaOut, tableSize); // move everything
}
return (Ptr)pTableGammaOut; // return whatever we allocated, could be NULL
}
// --------------------------------------------------------------------------
// DisposeGammaTable
// disposes gamma table returned from GetGammaTable, GetDeviceGamma, or CopyGammaTable
// 5/20/99: (GGS) added
void DisposeGammaTable (Ptr pGamma)
{
if (pGamma)
DisposePtr((Ptr) pGamma); // get rid of it
}
// --------------------------------------------------------------------------
// GetDeviceGamma
// returns pointer to copy of orginal device gamma table in native format (allocates memory for gamma table, call DisposeDeviceGamma to delete)
// 5/20/99: (GGS) change spec to return the allocated pointer vice storing internally
Ptr GetDeviceGamma (GDHandle hGD)
{
GammaTblPtr pTableGammaDevice = NULL;
GammaTblPtr pTableGammaReturn = NULL;
OSErr err;
err = GetGammaTable (hGD, &pTableGammaDevice); // get a pointer to the devices table
if ((err == noErr) && pTableGammaDevice) // if succesful
pTableGammaReturn = (GammaTblPtr) CopyGammaTable (pTableGammaDevice); // copy to global
return (Ptr) pTableGammaReturn;
}
// --------------------------------------------------------------------------
// RestoreDeviceGamma
// sets device to saved table
// 5/20/99: (GGS) now does not delete table, avoids confusion
void RestoreDeviceGamma (GDHandle hGD, Ptr pGammaTable)
{
VDSetEntryRecord setEntriesRec;
VDGammaRecord gameRecRestore;
CTabHandle hCTabDeviceColors;
Ptr csPtr;
OSErr err = noErr;
if (pGammaTable) // if we have a table to restore
{
gameRecRestore.csGTable = pGammaTable; // setup restore record
csPtr = (Ptr) &gameRecRestore;
err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); // restore gamma
if ((err == noErr) && ((**(**hGD).gdPMap).pixelSize == 8)) // if successful and on an 8 bit device
{
hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; // do SetEntries to force CLUT update
setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable;
setEntriesRec.csStart = 0;
setEntriesRec.csCount = (**hCTabDeviceColors).ctSize;
csPtr = (Ptr) &setEntriesRec;
err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); // SetEntries in CLUT
}
}
}
// --------------------------------------------------------------------------
// GetSystemGammas
// returns a pointer to a set of all current device gammas in native format (returns NULL on failure, which means reseting gamma will not be possible)
// 5/20/99: (GGS) added
Ptr GetSystemGammas (void)
{
precSystemGamma pSysGammaOut; // return pointer to system device gamma info
short devCount = 0; // number of devices attached
Boolean fail = false;
GDHandle hGDevice;
pSysGammaOut = (precSystemGamma) NewPtr (sizeof (recSystemGamma)); // allocate for structure
hGDevice = GetDeviceList (); // top of device list
do // iterate
{
devCount++; // count devices
hGDevice = GetNextDevice (hGDevice); // next device
} while (hGDevice);
pSysGammaOut->devGamma = (precDeviceGamma *) NewPtr (sizeof (precDeviceGamma) * devCount); // allocate for array of pointers to device records
if (pSysGammaOut)
{
pSysGammaOut->numDevices = devCount; // stuff count
devCount = 0; // reset iteration
hGDevice = GetDeviceList ();
do
{
pSysGammaOut->devGamma [devCount] = (precDeviceGamma) NewPtr (sizeof (recDeviceGamma)); // new device record
if (pSysGammaOut->devGamma [devCount]) // if we actually allocated memory
{
pSysGammaOut->devGamma [devCount]->hGD = hGDevice; // stuff handle
pSysGammaOut->devGamma [devCount]->pDeviceGamma = (GammaTblPtr)GetDeviceGamma (hGDevice); // copy gamma table
}
else // otherwise dump record on exit
fail = true;
devCount++; // next device
hGDevice = GetNextDevice (hGDevice);
} while (hGDevice);
}
if (!fail) // if we did not fail
return (Ptr) pSysGammaOut; // return pointer to structure
else
{
DisposeSystemGammas (&(Ptr)pSysGammaOut); // otherwise dump the current structures (dispose does error checking)
return NULL; // could not complete
}
}
// --------------------------------------------------------------------------
// RestoreSystemGammas
// restores all system devices to saved gamma setting
// 5/20/99: (GGS) added
void RestoreSystemGammas (Ptr pSystemGammas)
{
short i;
precSystemGamma pSysGammaIn = (precSystemGamma) pSystemGammas;
if (pSysGammaIn)
for ( i = 0; i < pSysGammaIn->numDevices; i++) // for all devices
RestoreDeviceGamma (pSysGammaIn->devGamma [i]->hGD, (Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); // restore gamma
}
// --------------------------------------------------------------------------
// DisposeSystemGammas
// iterates through and deletes stored gamma settings
// 5/20/99: (GGS) added
void DisposeSystemGammas (Ptr* ppSystemGammas)
{
precSystemGamma pSysGammaIn;
if (ppSystemGammas)
{
pSysGammaIn = (precSystemGamma) *ppSystemGammas;
if (pSysGammaIn)
{
short i;
for (i = 0; i < pSysGammaIn->numDevices; i++) // for all devices
if (pSysGammaIn->devGamma [i]) // if pointer is valid
{
DisposeGammaTable ((Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); // dump gamma table
DisposePtr ((Ptr) pSysGammaIn->devGamma [i]); // dump device info
}
DisposePtr ((Ptr) pSysGammaIn->devGamma); // dump device pointer array
DisposePtr ((Ptr) pSysGammaIn); // dump system structure
*ppSystemGammas = NULL;
}
}
}
// --------------------------------------------------------------------------
// GetDeviceGammaRampGD
// retrieves the gamma ramp from a graphics device (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp)
{
GammaTblPtr pTableGammaTemp = NULL;
long indexChan, indexEntry;
OSErr err;
if (pRamp) // ensure pRamp is allocated
{
err = GetGammaTable (hGD, &pTableGammaTemp); // get a pointer to the current gamma
if ((err == noErr) && pTableGammaTemp) // if successful
{
// fill ramp
unsigned char * pEntry = (unsigned char *)&pTableGammaTemp->gFormulaData + pTableGammaTemp->gFormulaSize; // base of table
short bytesPerEntry = (pTableGammaTemp->gDataWidth + 7) / 8; // size, in bytes, of the device table entries
short shiftRightValue = pTableGammaTemp->gDataWidth - 8; // number of right shifts device -> ramp
short channels = pTableGammaTemp->gChanCnt;
short entries = pTableGammaTemp->gDataCnt;
if (channels == 3) // RGB format
{ // note, this will create runs of entries if dest. is bigger (not linear interpolate)
for (indexChan = 0; indexChan < channels; indexChan++)
for (indexEntry = 0; indexEntry < 256; indexEntry++)
*((unsigned char *)pRamp + (indexChan << 8) + indexEntry) =
*(pEntry + (indexChan * entries * bytesPerEntry) + indexEntry * ((entries * bytesPerEntry) >> 8)) >> shiftRightValue;
}
else // single channel format
{
for (indexEntry = 0; indexEntry < 256; indexEntry++) // for all entries set vramp value
for (indexChan = 0; indexChan < channels; indexChan++) // repeat for all channels
*((unsigned char *)pRamp + (indexChan << 8) + indexEntry) =
*(pEntry + ((indexEntry * entries * bytesPerEntry) >> 8)) >> shiftRightValue;
}
return true;
}
}
return false;
}
// --------------------------------------------------------------------------
// GetDeviceGammaRampGW
// retrieves the gamma ramp from a graphics device associated with a GWorld pointer (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampGW (GWorldPtr pGW, Ptr pRamp)
{
GDHandle hGD = GetGWorldDevice (pGW);
return GetDeviceGammaRampGD (hGD, pRamp);
}
// --------------------------------------------------------------------------
// GetDeviceGammaRampCGP
// retrieves the gamma ramp from a graphics device associated with a CGraf pointer (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampCGP (CGrafPtr pGraf, Ptr pRamp)
{
CGrafPtr pGrafSave;
GDHandle hGDSave;
GDHandle hGD;
Boolean fResult;
GetGWorld (&pGrafSave, &hGDSave);
SetGWorld (pGraf, NULL);
hGD = GetGDevice ();
fResult = GetDeviceGammaRampGD (hGD, pRamp);
SetGWorld (pGrafSave, hGDSave);
return fResult;
}
// --------------------------------------------------------------------------
// SetDeviceGammaRampGD
// sets the gamma ramp for a graphics device (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp)
{
VDSetEntryRecord setEntriesRec;
VDGammaRecord gameRecRestore;
GammaTblPtr pTableGammaNew;
GammaTblPtr pTableGammaCurrent = NULL;
CTabHandle hCTabDeviceColors;
Ptr csPtr;
OSErr err;
short dataBits, entries, channels = 3; // force three channels in the gamma table
if (pRamp) // ensure pRamp is allocated
{
err= GetGammaTable (hGD, &pTableGammaCurrent); // get pointer to current table
if ((err == noErr) && pTableGammaCurrent)
{
dataBits = pTableGammaCurrent->gDataWidth; // table must have same data width
entries = pTableGammaCurrent->gDataCnt; // table must be same size
pTableGammaNew = (GammaTblPtr) CreateEmptyGammaTable (channels, entries, dataBits); // our new table
if (pTableGammaNew) // if successful fill table
{
unsigned char * pGammaBase = (unsigned char *)&pTableGammaNew->gFormulaData + pTableGammaNew->gFormulaSize; // base of table
if (entries == 256 && dataBits == 8) // simple case: direct mapping
BlockMove ((Ptr)pRamp, (Ptr)pGammaBase, channels * entries); // move everything
else // tough case handle entry, channel and data size disparities
{
short bytesPerEntry = (dataBits + 7) / 8; // size, in bytes, of the device table entries
short shiftRightValue = 8 - dataBits; // number of right shifts ramp -> device
short indexChan;
short indexEntry;
short indexByte;
shiftRightValue += ((bytesPerEntry - 1) * 8); // multibyte entries and the need to map a byte at a time most sig. to least sig.
for ( indexChan = 0; indexChan < channels; indexChan++) // for all the channels
for ( indexEntry = 0; indexEntry < entries; indexEntry++) // for all the entries
{
short currentShift = shiftRightValue; // reset current bit shift
long temp = *((unsigned char *)pRamp + (indexChan << 8) + (indexEntry << 8) / entries); // get data from ramp
for ( indexByte = 0; indexByte < bytesPerEntry; indexByte++) // for all bytes
{
if (currentShift < 0) // shift data correctly for current byte
*(pGammaBase++) = temp << -currentShift;
else
*(pGammaBase++) = temp >> currentShift;
currentShift -= 8; // increment shift to align to next less sig. byte
}
}
}
// set gamma
gameRecRestore.csGTable = (Ptr) pTableGammaNew; // setup restore record
csPtr = (Ptr) &gameRecRestore;
err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); // restore gamma
if (((**(**hGD).gdPMap).pixelSize == 8) && (err == noErr)) // if successful and on an 8 bit device
{
hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; // do SetEntries to force CLUT update
setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable;
setEntriesRec.csStart = 0;
setEntriesRec.csCount = (**hCTabDeviceColors).ctSize;
csPtr = (Ptr) &setEntriesRec;
err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); // SetEntries in CLUT
}
DisposeGammaTable ((Ptr) pTableGammaNew); // dump table
if (err == noErr)
return true;
}
}
}
else // set NULL gamma -> results in linear map
{
gameRecRestore.csGTable = (Ptr) NULL; // setup restore record
csPtr = (Ptr) &gameRecRestore;
err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); // restore gamma
if (((**(**hGD).gdPMap).pixelSize == 8) && (err == noErr)) // if successful and on an 8 bit device
{
hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; // do SetEntries to force CLUT update
setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable;
setEntriesRec.csStart = 0;
setEntriesRec.csCount = (**hCTabDeviceColors).ctSize;
csPtr = (Ptr) &setEntriesRec;
err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); // SetEntries in CLUT
}
if (err == noErr)
return true;
}
return false; // memory allocation or device control failed if we get here
}
// --------------------------------------------------------------------------
// SetDeviceGammaRampGW
// sets the gamma ramp for a graphics device associated with a GWorld pointer (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampGW (GWorldPtr pGW, Ptr pRamp)
{
GDHandle hGD = GetGWorldDevice (pGW);
return SetDeviceGammaRampGD (hGD, pRamp);
}
// --------------------------------------------------------------------------
// SetDeviceGammaRampCGP
// sets the gamma ramp for a graphics device associated with a CGraf pointer (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampCGP (CGrafPtr pGraf, Ptr pRamp)
{
CGrafPtr pGrafSave;
GDHandle hGDSave;
GDHandle hGD;
Boolean fResult;
GetGWorld (&pGrafSave, &hGDSave);
SetGWorld (pGraf, NULL);
hGD = GetGDevice ();
fResult = SetDeviceGammaRampGD (hGD, pRamp);
SetGWorld (pGrafSave, hGDSave);
return fResult;
}

474
code/mac/MacGamma.cpp Normal file
View File

@@ -0,0 +1,474 @@
/*
File: MacGamma.cpp
Contains: Functions to enable Mac OS device gamma adjustments using Windows common 3 channel 256 element 8 bit gamma ramps
Written by: Geoff Stahl
Copyright: Copyright © 1999 Apple Computer, Inc., All Rights Reserved
Change History (most recent first):
<4> 5/20/99 GGS Added handling for gamma tables with different data widths,
number of entries, and channels. Forced updates to 3 channels
(poss. could break on rare card, but very unlikely). Added
quick update with BlockMove for 3x256x8 tables. Updated function
names.
<3> 5/20/99 GGS Cleaned up and commented
<2> 5/20/99 GGS Added system wide get and restore gamma functions to enable
restoration of original for all devices. Modified functionality
to return pointers vice squirreling away the memory.
<1> 5/20/99 GGS Initial Add
*/
// system includes ----------------------------------------------------------
#include <Devices.h>
#include <Files.h>
#include <MacTypes.h>
#include <QDOffscreen.h>
#include <Quickdraw.h>
#include <video.h>
// project includes ---------------------------------------------------------
#include "MacGamma.h"
// functions (external/public) ----------------------------------------------
// GetRawDeviceGamma
// Returns the device gamma table pointer in ppDeviceTable
OSErr GetGammaTable (GDHandle hGD, GammaTblPtr * ppTableGammaOut)
{
VDGammaRecord DeviceGammaRec;
CntrlParam cParam;
OSErr err;
cParam.ioCompletion = NULL; // set up control params
cParam.ioNamePtr = NULL;
cParam.ioVRefNum = 0;
cParam.ioCRefNum = (**hGD).gdRefNum;
cParam.csCode = cscGetGamma; // Get Gamma commnd to device
*(Ptr *)cParam.csParam = (Ptr) &DeviceGammaRec; // record for gamma
err = PBStatus( (ParmBlkPtr)&cParam, 0 ); // get gamma
*ppTableGammaOut = (GammaTblPtr)(DeviceGammaRec.csGTable); // pull table out of record
return err;
}
// --------------------------------------------------------------------------
// CreateEmptyGammaTable
// creates an empty gamma table of a given size, assume no formula data will be used
Ptr CreateEmptyGammaTable (short channels, short entries, short bits)
{
GammaTblPtr pTableGammaOut = NULL;
short tableSize, dataWidth;
dataWidth = (bits + 7) / 8; // number of bytes per entry
tableSize = sizeof (GammaTbl) + (channels * entries * dataWidth);
pTableGammaOut = (GammaTblPtr) NewPtrClear (tableSize); // allocate new tabel
if (pTableGammaOut) // if we successfully allocated
{
pTableGammaOut->gVersion = 0; // set parameters based on input
pTableGammaOut->gType = 0;
pTableGammaOut->gFormulaSize = 0;
pTableGammaOut->gChanCnt = channels;
pTableGammaOut->gDataCnt = entries;
pTableGammaOut->gDataWidth = bits;
}
return (Ptr)pTableGammaOut; // return whatever we allocated
}
// --------------------------------------------------------------------------
// CopyGammaTable
// given a pointer toa device gamma table properly iterates and copies
Ptr CopyGammaTable (GammaTblPtr pTableGammaIn)
{
GammaTblPtr pTableGammaOut = NULL;
short tableSize, dataWidth;
if (pTableGammaIn) // if there is a table to copy
{
dataWidth = (pTableGammaIn->gDataWidth + 7) / 8; // number of bytes per entry
tableSize = sizeof (GammaTbl) + pTableGammaIn->gFormulaSize +
(pTableGammaIn->gChanCnt * pTableGammaIn->gDataCnt * dataWidth);
pTableGammaOut = (GammaTblPtr) NewPtr (tableSize); // allocate new table
if (pTableGammaOut)
BlockMove( (Ptr)pTableGammaIn, (Ptr)pTableGammaOut, tableSize); // move everything
}
return (Ptr)pTableGammaOut; // return whatever we allocated, could be NULL
}
// --------------------------------------------------------------------------
// DisposeGammaTable
// disposes gamma table returned from GetGammaTable, GetDeviceGamma, or CopyGammaTable
// 5/20/99: (GGS) added
void DisposeGammaTable (Ptr pGamma)
{
if (pGamma)
DisposePtr((Ptr) pGamma); // get rid of it
}
// --------------------------------------------------------------------------
// GetDeviceGamma
// returns pointer to copy of orginal device gamma table in native format (allocates memory for gamma table, call DisposeDeviceGamma to delete)
// 5/20/99: (GGS) change spec to return the allocated pointer vice storing internally
Ptr GetDeviceGamma (GDHandle hGD)
{
GammaTblPtr pTableGammaDevice = NULL;
GammaTblPtr pTableGammaReturn = NULL;
OSErr err;
err = GetGammaTable (hGD, &pTableGammaDevice); // get a pointer to the devices table
if ((err == noErr) && pTableGammaDevice) // if succesful
pTableGammaReturn = (GammaTblPtr) CopyGammaTable (pTableGammaDevice); // copy to global
return (Ptr) pTableGammaReturn;
}
// --------------------------------------------------------------------------
// RestoreDeviceGamma
// sets device to saved table
// 5/20/99: (GGS) now does not delete table, avoids confusion
void RestoreDeviceGamma (GDHandle hGD, Ptr pGammaTable)
{
VDSetEntryRecord setEntriesRec;
VDGammaRecord gameRecRestore;
CTabHandle hCTabDeviceColors;
Ptr csPtr;
OSErr err = noErr;
if (pGammaTable) // if we have a table to restore
{
gameRecRestore.csGTable = pGammaTable; // setup restore record
csPtr = (Ptr) &gameRecRestore;
err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); // restore gamma
if ((err == noErr) && ((**(**hGD).gdPMap).pixelSize == 8)) // if successful and on an 8 bit device
{
hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; // do SetEntries to force CLUT update
setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable;
setEntriesRec.csStart = 0;
setEntriesRec.csCount = (**hCTabDeviceColors).ctSize;
csPtr = (Ptr) &setEntriesRec;
err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); // SetEntries in CLUT
}
}
}
// --------------------------------------------------------------------------
// GetSystemGammas
// returns a pointer to a set of all current device gammas in native format (returns NULL on failure, which means reseting gamma will not be possible)
// 5/20/99: (GGS) added
Ptr GetSystemGammas (void)
{
precSystemGamma pSysGammaOut; // return pointer to system device gamma info
short devCount = 0; // number of devices attached
Boolean fail = false;
pSysGammaOut = (precSystemGamma) NewPtr (sizeof (recSystemGamma)); // allocate for structure
GDHandle hGDevice = GetDeviceList (); // top of device list
do // iterate
{
devCount++; // count devices
hGDevice = GetNextDevice (hGDevice); // next device
} while (hGDevice);
pSysGammaOut->devGamma = (precDeviceGamma *) NewPtr (sizeof (precDeviceGamma) * devCount); // allocate for array of pointers to device records
if (pSysGammaOut)
{
pSysGammaOut->numDevices = devCount; // stuff count
devCount = 0; // reset iteration
hGDevice = GetDeviceList ();
do
{
pSysGammaOut->devGamma [devCount] = (precDeviceGamma) NewPtr (sizeof (recDeviceGamma)); // new device record
if (pSysGammaOut->devGamma [devCount]) // if we actually allocated memory
{
pSysGammaOut->devGamma [devCount]->hGD = hGDevice; // stuff handle
pSysGammaOut->devGamma [devCount]->pDeviceGamma = (GammaTblPtr)GetDeviceGamma (hGDevice); // copy gamma table
}
else // otherwise dump record on exit
fail = true;
devCount++; // next device
hGDevice = GetNextDevice (hGDevice);
} while (hGDevice);
}
if (!fail) // if we did not fail
return (Ptr) pSysGammaOut; // return pointer to structure
else
{
DisposeSystemGammas (&(Ptr)pSysGammaOut); // otherwise dump the current structures (dispose does error checking)
return NULL; // could not complete
}
}
// --------------------------------------------------------------------------
// RestoreSystemGammas
// restores all system devices to saved gamma setting
// 5/20/99: (GGS) added
void RestoreSystemGammas (Ptr pSystemGammas)
{
precSystemGamma pSysGammaIn = (precSystemGamma) pSystemGammas;
if (pSysGammaIn)
for (short i = 0; i < pSysGammaIn->numDevices; i++) // for all devices
RestoreDeviceGamma (pSysGammaIn->devGamma [i]->hGD, (Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); // restore gamma
}
// --------------------------------------------------------------------------
// DisposeSystemGammas
// iterates through and deletes stored gamma settings
// 5/20/99: (GGS) added
void DisposeSystemGammas (Ptr* ppSystemGammas)
{
precSystemGamma pSysGammaIn;
if (ppSystemGammas)
{
pSysGammaIn = (precSystemGamma) *ppSystemGammas;
if (pSysGammaIn)
{
for (short i = 0; i < pSysGammaIn->numDevices; i++) // for all devices
if (pSysGammaIn->devGamma [i]) // if pointer is valid
{
DisposeGammaTable ((Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); // dump gamma table
DisposePtr ((Ptr) pSysGammaIn->devGamma [i]); // dump device info
}
DisposePtr ((Ptr) pSysGammaIn->devGamma); // dump device pointer array
DisposePtr ((Ptr) pSysGammaIn); // dump system structure
*ppSystemGammas = NULL;
}
}
}
// --------------------------------------------------------------------------
// GetDeviceGammaRampGD
// retrieves the gamma ramp from a graphics device (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp)
{
GammaTblPtr pTableGammaTemp = NULL;
long indexChan, indexEntry;
OSErr err;
if (pRamp) // ensure pRamp is allocated
{
err = GetGammaTable (hGD, &pTableGammaTemp); // get a pointer to the current gamma
if ((err == noErr) && pTableGammaTemp) // if successful
{
// fill ramp
unsigned char * pEntry = (unsigned char *)&pTableGammaTemp->gFormulaData + pTableGammaTemp->gFormulaSize; // base of table
short bytesPerEntry = (pTableGammaTemp->gDataWidth + 7) / 8; // size, in bytes, of the device table entries
short shiftRightValue = pTableGammaTemp->gDataWidth - 8; // number of right shifts device -> ramp
short channels = pTableGammaTemp->gChanCnt;
short entries = pTableGammaTemp->gDataCnt;
if (channels == 3) // RGB format
{ // note, this will create runs of entries if dest. is bigger (not linear interpolate)
for (indexChan = 0; indexChan < channels; indexChan++)
for (indexEntry = 0; indexEntry < 256; indexEntry++)
*((unsigned char *)pRamp + (indexChan << 8) + indexEntry) =
*(pEntry + (indexChan * entries * bytesPerEntry) + indexEntry * ((entries * bytesPerEntry) >> 8)) >> shiftRightValue;
}
else // single channel format
{
for (indexEntry = 0; indexEntry < 256; indexEntry++) // for all entries set vramp value
for (indexChan = 0; indexChan < channels; indexChan++) // repeat for all channels
*((unsigned char *)pRamp + (indexChan << 8) + indexEntry) =
*(pEntry + ((indexEntry * entries * bytesPerEntry) >> 8)) >> shiftRightValue;
}
return true;
}
}
return false;
}
// --------------------------------------------------------------------------
// GetDeviceGammaRampGW
// retrieves the gamma ramp from a graphics device associated with a GWorld pointer (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampGW (GWorldPtr pGW, Ptr pRamp)
{
GDHandle hGD = GetGWorldDevice (pGW);
return GetDeviceGammaRampGD (hGD, pRamp);
}
// --------------------------------------------------------------------------
// GetDeviceGammaRampCGP
// retrieves the gamma ramp from a graphics device associated with a CGraf pointer (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampCGP (CGrafPtr pGraf, Ptr pRamp)
{
CGrafPtr pGrafSave;
GDHandle hGDSave;
GetGWorld (&pGrafSave, &hGDSave);
SetGWorld (pGraf, NULL);
GDHandle hGD = GetGDevice ();
Boolean fResult = GetDeviceGammaRampGD (hGD, pRamp);
SetGWorld (pGrafSave, hGDSave);
return fResult;
}
// --------------------------------------------------------------------------
// SetDeviceGammaRampGD
// sets the gamma ramp for a graphics device (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp)
{
VDSetEntryRecord setEntriesRec;
VDGammaRecord gameRecRestore;
GammaTblPtr pTableGammaNew;
GammaTblPtr pTableGammaCurrent = NULL;
CTabHandle hCTabDeviceColors;
Ptr csPtr;
OSErr err;
short dataBits, entries, channels = 3; // force three channels in the gamma table
if (pRamp) // ensure pRamp is allocated
{
err= GetGammaTable (hGD, &pTableGammaCurrent); // get pointer to current table
if ((err == noErr) && pTableGammaCurrent)
{
dataBits = pTableGammaCurrent->gDataWidth; // table must have same data width
entries = pTableGammaCurrent->gDataCnt; // table must be same size
pTableGammaNew = (GammaTblPtr) CreateEmptyGammaTable (channels, entries, dataBits); // our new table
if (pTableGammaNew) // if successful fill table
{
unsigned char * pGammaBase = (unsigned char *)&pTableGammaNew->gFormulaData + pTableGammaNew->gFormulaSize; // base of table
if (entries == 256 && dataBits == 8) // simple case: direct mapping
BlockMove ((Ptr)pRamp, (Ptr)pGammaBase, channels * entries); // move everything
else // tough case handle entry, channel and data size disparities
{
short bytesPerEntry = (dataBits + 7) / 8; // size, in bytes, of the device table entries
short shiftRightValue = 8 - dataBits; // number of right shifts ramp -> device
shiftRightValue += ((bytesPerEntry - 1) * 8); // multibyte entries and the need to map a byte at a time most sig. to least sig.
for (short indexChan = 0; indexChan < channels; indexChan++) // for all the channels
for (short indexEntry = 0; indexEntry < entries; indexEntry++) // for all the entries
{
short currentShift = shiftRightValue; // reset current bit shift
long temp = *((unsigned char *)pRamp + (indexChan << 8) + (indexEntry << 8) / entries); // get data from ramp
for (short indexByte = 0; indexByte < bytesPerEntry; indexByte++) // for all bytes
{
if (currentShift < 0) // shift data correctly for current byte
*(pGammaBase++) = temp << -currentShift;
else
*(pGammaBase++) = temp >> currentShift;
currentShift -= 8; // increment shift to align to next less sig. byte
}
}
}
// set gamma
gameRecRestore.csGTable = (Ptr) pTableGammaNew; // setup restore record
csPtr = (Ptr) &gameRecRestore;
err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); // restore gamma
if (((**(**hGD).gdPMap).pixelSize == 8) && (err == noErr)) // if successful and on an 8 bit device
{
hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; // do SetEntries to force CLUT update
setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable;
setEntriesRec.csStart = 0;
setEntriesRec.csCount = (**hCTabDeviceColors).ctSize;
csPtr = (Ptr) &setEntriesRec;
err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); // SetEntries in CLUT
}
DisposeGammaTable ((Ptr) pTableGammaNew); // dump table
if (err == noErr)
return true;
}
}
}
else // set NULL gamma -> results in linear map
{
gameRecRestore.csGTable = (Ptr) NULL; // setup restore record
csPtr = (Ptr) &gameRecRestore;
err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); // restore gamma
if (((**(**hGD).gdPMap).pixelSize == 8) && (err == noErr)) // if successful and on an 8 bit device
{
hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; // do SetEntries to force CLUT update
setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable;
setEntriesRec.csStart = 0;
setEntriesRec.csCount = (**hCTabDeviceColors).ctSize;
csPtr = (Ptr) &setEntriesRec;
err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); // SetEntries in CLUT
}
if (err == noErr)
return true;
}
return false; // memory allocation or device control failed if we get here
}
// --------------------------------------------------------------------------
// SetDeviceGammaRampGW
// sets the gamma ramp for a graphics device associated with a GWorld pointer (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampGW (GWorldPtr pGW, Ptr pRamp)
{
GDHandle hGD = GetGWorldDevice (pGW);
return SetDeviceGammaRampGD (hGD, pRamp);
}
// --------------------------------------------------------------------------
// SetDeviceGammaRampCGP
// sets the gamma ramp for a graphics device associated with a CGraf pointer (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampCGP (CGrafPtr pGraf, Ptr pRamp)
{
CGrafPtr pGrafSave;
GDHandle hGDSave;
GetGWorld (&pGrafSave, &hGDSave);
SetGWorld (pGraf, NULL);
GDHandle hGD = GetGDevice ();
Boolean fResult = SetDeviceGammaRampGD (hGD, pRamp);
SetGWorld (pGrafSave, hGDSave);
return fResult;
}

82
code/mac/MacGamma.h Normal file
View File

@@ -0,0 +1,82 @@
/*
File: MacGamma.h
Contains: Functions to enable Mac OS device gamma adjustments using Windows common 3 channel 256 element 8 bit gamma ramps
Written by: Geoff Stahl
Copyright: Copyright © 1999 Apple Computer, Inc., All Rights Reserved
Change History (most recent first):
<4> 5/20/99 GGS Updated function names.
<3> 5/20/99 GGS Cleaned up and commented
<2> 5/20/99 GGS Added system wide get and restore gamma functions to enable
restoration of original for all devices. Modified functionality
to return pointers vice squirreling away the memory.
<1> 5/20/99 GGS Initial Add
*/
// include control --------------------------------------------------
#ifndef MacGamma_h
#define MacGamma_h
// includes ---------------------------------------------------------
#include <Quickdraw.h>
#include <QDOffscreen.h>
// structures/classes -----------------------------------------------
typedef struct // storage for device handle and gamma table
{
GDHandle hGD; // handle to device
GammaTblPtr pDeviceGamma; // pointer to device gamma table
} recDeviceGamma;
typedef recDeviceGamma * precDeviceGamma;
typedef struct // storage for system devices and gamma tables
{
short numDevices; // number of devices
precDeviceGamma * devGamma; // array of pointers to device gamma records
} recSystemGamma;
typedef recSystemGamma * precSystemGamma;
// function declarations --------------------------------------------
// 5/20/99: (GGS) changed functional specification
OSErr GetGammaTable(GDHandle gd, GammaTblPtr * ppTableGammaOut); // Returns the device gamma table pointer in ppDeviceTable
Ptr CreateEmptyGammaTable (short channels, short entries, short bits); // creates an empty gamma table of a given size, assume no formula data will be used
Ptr CopyGammaTable (GammaTblPtr pTableGammaIn); // given a pointer toa device gamma table properly iterates and copies
void DisposeGammaTable (Ptr pGamma); // disposes gamma table returned from GetGammaTable, GetDeviceGamma, or CopyGammaTable
Ptr GetDeviceGamma (GDHandle hGD); // returns pointer to copy of orginal device gamma table in native format
void RestoreDeviceGamma (GDHandle hGD, Ptr pGammaTable); // sets device to saved table
// 5/20/99: (GGS) added system wide gamma get and restore
Ptr GetSystemGammas (void); // returns a pointer to a set of all current device gammas in native format
// (returns NULL on failure, which means reseting gamma will not be possible)
void RestoreSystemGammas (Ptr pSystemGammas); // restores all system devices to saved gamma setting
void DisposeSystemGammas (Ptr* ppSystemGammas); // iterates through and deletes stored gamma settings
Boolean GetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp); // retrieves the gamma ramp from a graphics device (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampGW (GWorldPtr pGW, Ptr pRamp); // retrieves the gamma ramp from a graphics device associated with a GWorld pointer (pRamp: 3 arrays of 256 elements each)
Boolean GetDeviceGammaRampCGP (CGrafPtr pGraf, Ptr pRamp); // retrieves the gamma ramp from a graphics device associated with a CGraf pointer (pRamp: 3 arrays of 256 elements each)
Boolean SetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp); // sets the gamma ramp for a graphics device (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampGW (GWorldPtr pGW, Ptr pRamp); // sets the gamma ramp for a graphics device associated with a GWorld pointer (pRamp: 3 arrays of 256 elements each (R,G,B))
Boolean SetDeviceGammaRampCGP (CGrafPtr pGraf, Ptr pRamp); // sets the gamma ramp for a graphics device associated with a CGraf pointer (pRamp: 3 arrays of 256 elements each (R,G,B))
#endif // MacGamma_h

BIN
code/mac/MacQuake3 Normal file

Binary file not shown.

119
code/mac/mac_console.c Normal file
View File

@@ -0,0 +1,119 @@
#include "../client/client.h"
#include "mac_local.h"
#include <DriverServices.h>
#include <console.h>
#define CONSOLE_MASK 1023
static char consoleChars[CONSOLE_MASK+1];
static int consoleHead, consoleTail;
static qboolean consoleDisplayed;
/*
==================
Sys_InitConsole
==================
*/
void Sys_InitConsole( void ) {
SIOUXSettings.initializeTB = 0;
SIOUXSettings.standalone = 0;
SIOUXSettings.setupmenus = 0;
SIOUXSettings.autocloseonquit = 1;
SIOUXSettings.asktosaveonclose = 0;
SIOUXSettings.toppixel = 40;
SIOUXSettings.leftpixel = 10;
// Sys_ShowConsole( 1, qfalse );
}
/*
==================
Sys_ShowConsole
==================
*/
void Sys_ShowConsole( int level, qboolean quitOnClose ) {
if ( level ) {
consoleDisplayed = qtrue;
printf( "\n" );
} else {
// FIXME: I don't know how to hide this window...
consoleDisplayed = qfalse;
}
}
/*
================
Sys_Print
This is called for all console output, even if the game is running
full screen and the dedicated console window is hidden.
================
*/
void Sys_Print( const char *text ) {
if ( !consoleDisplayed ) {
return;
}
printf( "%s", text );
}
/*
==================
Sys_ConsoleEvent
==================
*/
qboolean Sys_ConsoleEvent( EventRecord *event ) {
qboolean flag;
flag = SIOUXHandleOneEvent(event);
// track keyboard events so we can do console input,
// because SIOUX doesn't offer a polled read as far
// as I can tell...
if ( flag && event->what == keyDown ) {
int myCharCode;
myCharCode = BitAnd( event->message, charCodeMask );
if ( myCharCode == 8 || myCharCode == 28 ) {
if ( consoleHead > consoleTail ) {
consoleHead--;
}
} else if ( myCharCode >= 32 || myCharCode == 13 ) {
consoleChars[ consoleHead & CONSOLE_MASK ] = myCharCode;
consoleHead++;
}
}
return flag;
}
/*
================
Sys_ConsoleInput
Checks for a complete line of text typed in at the console.
Return NULL if a complete line is not ready.
================
*/
char *Sys_ConsoleInput( void ) {
static char string[1024];
int i;
if ( consoleTail == consoleHead ) {
return NULL;
}
for ( i = 0 ; i + consoleTail < consoleHead ; i++ ) {
string[i] = consoleChars[ ( consoleTail + i ) & CONSOLE_MASK ];
if ( string[i] == 13 ) {
consoleTail += i + 1;
string[i] = 0;
return string;
}
}
return NULL;
}

357
code/mac/mac_event.c Normal file
View File

@@ -0,0 +1,357 @@
#include "../client/client.h"
#include "mac_local.h"
void DoMenuCommand(long menuAndItem);
void DoDrag(WindowPtr myWindow,Point mouseloc);
void DoGoAwayBox(WindowPtr myWindow, Point mouseloc);
void DoCloseWindow(WindowPtr myWindow);
void DoKeyDown(EventRecord *event);
void DoDiskEvent(EventRecord *event);
void DoOSEvent(EventRecord *event);
void DoUpdate(WindowPtr myWindow);
void DoActivate(WindowPtr myWindow, int myModifiers);
void DoAboutBox(void);
void DoMenuCommand(long menuAndItem);
void DoMouseDown(EventRecord *event);
void DoMouseUp(EventRecord *event);
void DoMenuAdjust(void);
void DoKeyUp(EventRecord *event);
/*
================
Sys_MsecForMacEvent
Q3 event records take time in msec,
so convert the mac event record when
(60ths) to msec. The base values
are updated ever frame, so this
is guaranteed to not drift.
=================
*/
int Sys_MsecForMacEvent( void ) {
int tics;
tics = sys_lastEventTic - sys_ticBase;
return sys_msecBase + tics * 16;
}
void DoMouseDown(EventRecord *event)
{
int myPart;
WindowPtr myWindow;
Point point;
myPart = FindWindow(event->where, &myWindow);
switch(myPart)
{
case inMenuBar:
DrawMenuBar();
DoMenuCommand(MenuSelect(event->where));
break;
case inSysWindow:
SystemClick(event, myWindow);
break;
case inDrag:
DoDrag(myWindow, event->where);
// update the vid_xpos / vid_ypos cvars
point.h = 0;
point.v = 0;
LocalToGlobal( &point );
Cvar_SetValue( "vid_xpos", point.h );
Cvar_SetValue( "vid_ypos", point.v );
return;
break;
case inGoAway:
DoGoAwayBox(myWindow, event->where);
break;
case inContent:
if (myWindow != FrontWindow())
{
SelectWindow(myWindow);
}
break;
}
}
void DoMouseUp(EventRecord *event)
{
}
void DoDrag(WindowPtr myWindow, Point mouseloc)
{
Rect dragBounds;
dragBounds = (**GetGrayRgn()).rgnBBox;
DragWindow(myWindow,mouseloc,&dragBounds);
aglUpdateContext(aglGetCurrentContext());
}
void DoGoAwayBox(WindowPtr myWindow, Point mouseloc)
{
if(TrackGoAway(myWindow,mouseloc))
{
DoCloseWindow(myWindow);
}
}
void DoCloseWindow(WindowPtr myWindow)
{
}
void DoMenuAdjust(void)
{
}
int vkeyToQuakeKey[256] = {
/*0x00*/ 'a', 's', 'd', 'f', 'h', 'g', 'z', 'x',
/*0x08*/ 'c', 'v', '?', 'b', 'q', 'w', 'e', 'r',
/*0x10*/ 'y', 't', '1', '2', '3', '4', '6', '5',
/*0x18*/ '=', '9', '7', '-', '8', '0', ']', 'o',
/*0x20*/ 'u', '[', 'i', 'p', K_ENTER, 'l', 'j', '\'',
/*0x28*/ 'k', ';', '\\', ',', '/', 'n', 'm', '.',
/*0x30*/ K_TAB, K_SPACE, '`', K_BACKSPACE, '?', K_ESCAPE, '?', K_COMMAND,
/*0x38*/ K_SHIFT, K_CAPSLOCK, K_ALT, K_CTRL, '?', '?', '?', '?',
/*0x40*/ '?', K_KP_DEL, '?', K_KP_STAR, '?', K_KP_PLUS, '?', K_KP_NUMLOCK,
/*0x48*/ '?', '?', '?', K_KP_SLASH, K_KP_ENTER, '?', K_KP_MINUS, '?',
/*0x50*/ '?', K_KP_EQUALS, K_KP_INS, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5,
/*0x58*/ K_KP_RIGHTARROW, K_KP_HOME, '?', K_KP_UPARROW, K_KP_PGUP, '?', '?', '?',
/*0x60*/ K_F5, K_F6, K_F7, K_F3, K_F8, K_F9, '?', K_F11,
/*0x68*/ '?', K_F13, '?', K_F14, '?', K_F10, '?', K_F12,
/*0x70*/ '?', K_F15, K_INS, K_HOME, K_PGUP, K_DEL, K_F4, K_END,
/*0x78*/ K_F2, K_PGDN, K_F1, K_LEFTARROW, K_RIGHTARROW, K_DOWNARROW, K_UPARROW, K_POWER
};
void DoKeyDown(EventRecord *event)
{
int myCharCode;
int myKeyCode;
myCharCode = BitAnd(event->message,charCodeMask);
myKeyCode = ( event->message & keyCodeMask ) >> 8;
Sys_QueEvent( Sys_MsecForMacEvent(), SE_KEY, vkeyToQuakeKey[ myKeyCode ], 1, 0, NULL );
Sys_QueEvent( Sys_MsecForMacEvent(), SE_CHAR, myCharCode, 0, 0, NULL );
}
void DoKeyUp(EventRecord *event)
{
int myCharCode;
int myKeyCode;
myCharCode = BitAnd(event->message,charCodeMask);
myKeyCode = ( event->message & keyCodeMask ) >> 8;
Sys_QueEvent( Sys_MsecForMacEvent(), SE_KEY, vkeyToQuakeKey[ myKeyCode ], 0, 0, NULL );
}
/*
==================
Sys_ModifierEvents
==================
*/
static void Sys_ModifierEvents( int modifiers ) {
static int oldModifiers;
int changed;
int i;
typedef struct {
int bit;
int keyCode;
} modifierKey_t;
static modifierKey_t keys[] = {
{ 128, K_MOUSE1 },
{ 256, K_COMMAND },
{ 512, K_SHIFT },
{1024, K_CAPSLOCK },
{2048, K_ALT },
{4096, K_CTRL },
{-1, -1 }
};
changed = modifiers ^ oldModifiers;
for ( i = 0 ; keys[i].bit != -1 ; i++ ) {
// if we have input sprockets running, ignore mouse events we
// get from the debug passthrough driver
if ( inputActive && keys[i].keyCode == K_MOUSE1 ) {
continue;
}
if ( changed & keys[i].bit ) {
Sys_QueEvent( Sys_MsecForMacEvent(),
SE_KEY, keys[i].keyCode, !!( modifiers & keys[i].bit ), 0, NULL );
}
}
oldModifiers = modifiers;
}
static void DoDiskEvent(EventRecord *event)
{
}
static void DoOSEvent(EventRecord *event)
{
}
static void DoUpdate(WindowPtr myWindow)
{
GrafPtr origPort;
GetPort(&origPort);
SetPort(myWindow);
BeginUpdate(myWindow);
EndUpdate(myWindow);
aglUpdateContext(aglGetCurrentContext());
SetPort(origPort);
}
static void DoActivate( WindowPtr myWindow, int myModifiers) {
}
static void DoAboutBox( void ) {
DialogPtr myDialog;
short itemHit;
myDialog = GetNewDialog(kAboutDialog, nil, (WindowPtr) -1);
ModalDialog(nil, &itemHit);
DisposeDialog(myDialog);
}
static void DoMenuCommand( long menuAndItem ) {
int myMenuNum;
int myItemNum;
int myResult;
Str255 myDAName;
WindowPtr myWindow;
myMenuNum = HiWord(menuAndItem);
myItemNum = LoWord(menuAndItem);
GetPort(&myWindow);
switch (myMenuNum) {
case mApple:
switch( myItemNum ) {
case iAbout:
DoAboutBox();
break;
default:
GetMenuItemText(GetMenuHandle(mApple), myItemNum, myDAName);
myResult = OpenDeskAcc(myDAName);
break;
}
break;
case mFile:
switch (myItemNum) {
case iQuit:
Com_Quit_f();
break;
}
break;
}
HiliteMenu(0);
}
void TestTime( EventRecord *ev ) {
int msec;
int tics;
static int startTics, startMsec;
msec = Sys_Milliseconds();
tics = ev->when;
if ( !startTics || ev->what == mouseDown ) {
startTics = tics;
startMsec = msec;
}
msec -= startMsec;
tics -= startTics;
if ( !tics ) {
return;
}
Com_Printf( "%i msec to tic\n", msec / tics );
}
/*
==================
Sys_SendKeyEvents
==================
*/
void Sys_SendKeyEvents (void) {
Boolean gotEvent;
EventRecord event;
if ( !glConfig.isFullscreen || sys_waitNextEvent->value ) {
// this call involves 68k code and task switching.
// do it on the desktop, or if they explicitly ask for
// it when fullscreen
gotEvent = WaitNextEvent(everyEvent, &event, 0, nil);
} else {
gotEvent = GetOSEvent( everyEvent, &event );
}
// generate faked events from modifer changes
Sys_ModifierEvents( event.modifiers );
sys_lastEventTic = event.when;
if ( !gotEvent ) {
return;
}
if ( Sys_ConsoleEvent(&event) ) {
return;
}
switch(event.what)
{
case mouseDown:
DoMouseDown(&event);
break;
case mouseUp:
DoMouseUp(&event);
break;
case keyDown:
DoKeyDown(&event);
break;
case keyUp:
DoKeyUp(&event);
break;
case autoKey:
DoKeyDown(&event);
break;
case updateEvt:
DoUpdate((WindowPtr) event.message);
break;
case diskEvt:
DoDiskEvent(&event);
break;
case activateEvt:
DoActivate((WindowPtr) event.message, event.modifiers);
break;
case osEvt:
DoOSEvent(&event);
break;
default:
break;
}
}

829
code/mac/mac_glimp.c Normal file
View File

@@ -0,0 +1,829 @@
typedef int sysEventType_t; // FIXME...
#include "../renderer/tr_local.h"
#include "mac_local.h"
#include <glm.h>
#include <DrawSprocket.h>
#include "MacGamma.h"
#define MAX_DEVICES 32
typedef struct {
GDHandle devices[MAX_DEVICES];
int numDevices;
Ptr systemGammas;
GDHandle device;
AGLContext context;
AGLDrawable drawable;
AGLPixelFormat fmt;
GLint textureMemory;
GLint videoMemory;
DSpContextReference DSpContext;
} macGlInfo;
cvar_t *r_device;
cvar_t *r_ext_transform_hint;
glHardwareType_t sys_hardwareType;
macGlInfo sys_gl;
void GLimp_EndFrame( void );
static void GLimp_Extensions( void );
void CToPStr(char *cs, Str255 ps)
{
GLint i, l;
l = strlen(cs);
if(l > 255) l = 255;
ps[0] = l;
for(i = 0; i < l; i++) ps[i + 1] = cs[i];
}
/*
============
CheckErrors
============
*/
void CheckErrors( void ) {
GLenum err;
err = aglGetError();
if( err != AGL_NO_ERROR ) {
ri.Error( ERR_FATAL, "aglGetError: %s",
aglErrorString( err ) );
}
}
//=======================================================================
/*
=====================
GLimp_ResetDisplay
=====================
*/
void GLimp_ResetDisplay( void ) {
if ( !glConfig.isFullscreen ) {
return;
}
glConfig.isFullscreen = qfalse;
// put the context into the inactive state
DSpContext_SetState( sys_gl.DSpContext, kDSpContextState_Inactive );
// release the context
DSpContext_Release( sys_gl.DSpContext );
// shutdown draw sprockets
DSpShutdown();
}
/*
=====================
GLimp_ChangeDisplay
=====================
*/
void GLimp_ChangeDisplay( int *actualWidth, int *actualHeight ) {
OSStatus theError;
DSpContextAttributes inAttributes;
int colorBits;
// startup DrawSprocket
theError = DSpStartup();
if( theError ) {
ri.Printf( PRINT_ALL, "DSpStartup() failed: %i\n", theError );
*actualWidth = 640;
*actualHeight = 480;
return;
}
if ( r_colorbits->integer == 24 || r_colorbits->integer == 32 ) {
colorBits = kDSpDepthMask_32;
} else {
colorBits = kDSpDepthMask_16;
}
memset( &inAttributes, 0, sizeof( inAttributes ) );
inAttributes.frequency = 0;
inAttributes.displayWidth = glConfig.vidWidth;
inAttributes.displayHeight = glConfig.vidHeight;
inAttributes.reserved1 = 0;
inAttributes.reserved2 = 0;
inAttributes.colorNeeds = kDSpColorNeeds_Require;
inAttributes.colorTable = NULL;
inAttributes.contextOptions = 0;
inAttributes.backBufferDepthMask = colorBits;
inAttributes.displayDepthMask = colorBits;
inAttributes.backBufferBestDepth = colorBits;
inAttributes.displayBestDepth = colorBits;
inAttributes.pageCount = 1;
inAttributes.gameMustConfirmSwitch = false;
inAttributes.reserved3[0] = 0;
inAttributes.reserved3[1] = 0;
inAttributes.reserved3[2] = 0;
inAttributes.reserved3[3] = 0;
theError = DSpFindBestContext( &inAttributes, &sys_gl.DSpContext );
inAttributes.displayWidth = glConfig.vidWidth;
inAttributes.displayHeight = glConfig.vidHeight;
inAttributes.backBufferDepthMask = colorBits;
inAttributes.displayDepthMask = colorBits;
inAttributes.backBufferBestDepth = colorBits;
inAttributes.displayBestDepth = colorBits;
inAttributes.pageCount = 1;
theError = DSpContext_Reserve( sys_gl.DSpContext, &inAttributes );
// find out what res we actually got
theError = DSpContext_GetAttributes( sys_gl.DSpContext, &inAttributes );
*actualWidth = inAttributes.displayWidth;
*actualHeight = inAttributes.displayHeight;
// put the context into the active state
theError = DSpContext_SetState( sys_gl.DSpContext, kDSpContextState_Active );
// fade back in
theError = DSpContext_FadeGammaIn( NULL, NULL );
glConfig.isFullscreen = qtrue;
}
//=======================================================================
/*
===================
GLimp_AglDescribe_f
===================
*/
void GLimp_AglDescribe_f( void ) {
long value;
long r,g,b,a;
long stencil, depth;
ri.Printf( PRINT_ALL, "Selected pixel format 0x%x\n", (int)sys_gl.fmt );
ri.Printf( PRINT_ALL, "TEXTURE_MEMORY: %i\n", sys_gl.textureMemory );
ri.Printf( PRINT_ALL, "VIDEO_MEMORY: %i\n", sys_gl.videoMemory );
aglDescribePixelFormat(sys_gl.fmt, AGL_RED_SIZE, &r);
aglDescribePixelFormat(sys_gl.fmt, AGL_GREEN_SIZE, &g);
aglDescribePixelFormat(sys_gl.fmt, AGL_BLUE_SIZE, &b);
aglDescribePixelFormat(sys_gl.fmt, AGL_ALPHA_SIZE, &a);
aglDescribePixelFormat(sys_gl.fmt, AGL_STENCIL_SIZE, &stencil);
aglDescribePixelFormat(sys_gl.fmt, AGL_DEPTH_SIZE, &depth);
ri.Printf( PRINT_ALL, "red:%i green:%i blue:%i alpha:%i depth:%i stencil:%i\n",
r, g, b, a, depth, stencil );
aglDescribePixelFormat(sys_gl.fmt, AGL_BUFFER_SIZE, &value);
ri.Printf( PRINT_ALL, "BUFFER_SIZE: %i\n", value );
aglDescribePixelFormat(sys_gl.fmt, AGL_PIXEL_SIZE, &value);
ri.Printf( PRINT_ALL, "PIXEL_SIZE: %i\n", value );
aglDescribePixelFormat(sys_gl.fmt, AGL_RENDERER_ID, &value);
ri.Printf( PRINT_ALL, "RENDERER_ID: %i\n", value );
// memory functions
value = glmGetInteger( GLM_PAGE_SIZE );
ri.Printf( PRINT_ALL, "GLM_PAGE_SIZE: %i\n", value );
value = glmGetInteger( GLM_NUMBER_PAGES );
ri.Printf( PRINT_ALL, "GLM_NUMBER_PAGES: %i\n", value );
value = glmGetInteger( GLM_CURRENT_MEMORY );
ri.Printf( PRINT_ALL, "GLM_CURRENT_MEMORY: %i\n", value );
value = glmGetInteger( GLM_MAXIMUM_MEMORY );
ri.Printf( PRINT_ALL, "GLM_MAXIMUM_MEMORY: %i\n", value );
}
/*
===================
GLimp_AglState_f
===================
*/
void GLimp_AglState_f( void ) {
char *cmd;
int state, value;
if ( ri.Cmd_Argc() != 3 ) {
ri.Printf( PRINT_ALL, "Usage: aglstate <parameter> <0/1>\n" );
return;
}
cmd = ri.Cmd_Argv( 1 );
if ( !Q_stricmp( cmd, "rasterization" ) ) {
state = AGL_RASTERIZATION;
} else {
ri.Printf( PRINT_ALL, "Unknown agl state: %s\n", cmd );
return;
}
cmd = ri.Cmd_Argv( 2 );
value = atoi( cmd );
if ( value ) {
aglEnable( sys_gl.context, state );
} else {
aglDisable( sys_gl.context, state );
}
}
/*
===================
GLimp_Extensions
===================
*/
static void GLimp_Extensions( void ) {
const char *extensions;
// get our config strings
Q_strncpyz( glConfig.vendor_string, (const char *)qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) );
Q_strncpyz( glConfig.renderer_string, (const char *)qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) );
Q_strncpyz( glConfig.version_string, (const char *)qglGetString (GL_VERSION), sizeof( glConfig.version_string ) );
Q_strncpyz( glConfig.extensions_string, (const char *)qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) );
extensions = glConfig.extensions_string;
// GL_ARB_multitexture
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
if ( strstr( extensions, "GL_ARB_multitexture" ) ) {
if ( r_ext_multitexture->integer && r_allowExtensions->integer ) {
qglMultiTexCoord2fARB = glMultiTexCoord2fARB;
qglActiveTextureARB = glActiveTextureARB;
qglClientActiveTextureARB = glClientActiveTextureARB;
ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
} else {
ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
}
// GL_EXT_compiled_vertex_array
qglLockArraysEXT = NULL;
qglUnlockArraysEXT = NULL;
if ( strstr( extensions, "GL_EXT_compiled_vertex_array" ) ) {
if ( r_ext_compiled_vertex_array->integer && r_allowExtensions->integer ) {
qglLockArraysEXT = glLockArraysEXT;
qglUnlockArraysEXT = glUnlockArraysEXT;
ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
} else {
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
// GL_EXT_texture_env_add
glConfig.textureEnvAddAvailable = qfalse;
if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) ) {
if ( r_ext_texture_env_add->integer ) {
glConfig.textureEnvAddAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
} else {
glConfig.textureEnvAddAvailable = qfalse;
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
}
// GL_EXT_texture_filter_anisotropic
glConfig.textureFilterAnisotropicAvailable = qfalse;
if ( strstr( glConfig.extensions_string, "EXT_texture_filter_anisotropic" ) )
{
glConfig.textureFilterAnisotropicAvailable = qtrue;
ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic available\n" );
if ( r_ext_texture_filter_anisotropic->integer )
{
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic\n" );
}
else
{
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" );
}
ri.Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "1" );
}
else
{
ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" );
ri.Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "0" );
}
// apple transform hint
if ( strstr( extensions, "GL_APPLE_transform_hint" ) ) {
if ( r_ext_compiled_vertex_array->integer && r_allowExtensions->integer ) {
glHint( GL_TRANSFORM_HINT_APPLE, GL_FASTEST );
ri.Printf( PRINT_ALL, "...using GL_APPLE_transform_hint\n" );
} else {
ri.Printf( PRINT_ALL, "...ignoring GL_APPLE_transform_hint\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_APPLE_transform_hint not found\n" );
}
}
/*
============================
GLimp_SufficientVideoMemory
============================
*/
#if 0
qboolean GLimp_SufficientVideoMemory( void ) {
AGLRendererInfo head_info, info;
GLint accelerated;
AGLDevice *device;
GLint i, ndevs;
device = aglDevicesOfPixelFormat( sys_gl.fmt, &ndevs);
if (!device || ndevs < 1) {
ri.Printf( PRINT_ALL, "aglDevicesOfPixelFormat failed.\n" );
return 0;
}
ri.Printf( PRINT_ALL, "%i rendering devices\n", ndevs );
head_info = aglQueryRendererInfo( device, 1 );
info = head_info;
if (!info) {
ri.Printf( PRINT_ALL, "aglQueryRendererInfo failed.\n" );
return 0;
}
for ( i = 0 ; i < ndevs ; i++ ) {
// ignore the software renderer listing
aglDescribeRenderer( info, AGL_ACCELERATED, &accelerated );
if ( accelerated ) {
aglDescribeRenderer( info, AGL_TEXTURE_MEMORY, &sys_gl.textureMemory );
aglDescribeRenderer( info, AGL_VIDEO_MEMORY, &sys_gl.videoMemory );
}
info = aglNextRendererInfo(info);
}
aglDestroyRendererInfo(head_info);
#if 0
if ( sys_gl.videoMemory < 16000000 ) {
glConfig.hardwareType = GLHW_RAGEPRO; // FIXME when voodoo is available
} else {
glConfig.isRagePro = GLHW_GENERIC; // FIXME when voodoo is available
}
#endif
ri.Printf( PRINT_ALL, "%i texture memory, %i video memory\n", sys_gl.textureMemory, sys_gl.videoMemory );
return qtrue;
}
#endif
/*
=======================
CheckDeviceRenderers
========================
*/
static void CheckDeviceRenderers( GDHandle device ) {
AGLRendererInfo info, head_info;
GLint inum;
GLint accelerated;
GLint textureMemory, videoMemory;
head_info = aglQueryRendererInfo(&device, 1);
if( !head_info ) {
ri.Printf( PRINT_ALL, "aglQueryRendererInfo : Info Error\n");
return;
}
info = head_info;
inum = 0;
while( info ) {
ri.Printf( PRINT_ALL, " Renderer : %d\n", inum);
aglDescribeRenderer( info, AGL_ACCELERATED, &accelerated );
if ( accelerated ) {
aglDescribeRenderer( info, AGL_TEXTURE_MEMORY, &textureMemory );
aglDescribeRenderer( info, AGL_VIDEO_MEMORY, &videoMemory );
ri.Printf( PRINT_ALL, " AGL_VIDEO_MEMORY: %i\n", textureMemory );
ri.Printf( PRINT_ALL, " AGL_TEXTURE_MEMORY: %i\n", videoMemory );
// save the device with the most texture memory
if ( sys_gl.textureMemory < textureMemory ) {
sys_gl.textureMemory = textureMemory;
sys_gl.device = device;
}
} else {
ri.Printf( PRINT_ALL, " Not accelerated.\n" );
}
info = aglNextRendererInfo(info);
inum++;
}
aglDestroyRendererInfo(head_info);
}
/*
=======================
CheckDevices
Make sure there is a device with enough video memory to play
=======================
*/
static void CheckDevices( void ) {
GDHandle device;
static qboolean checkedFullscreen;
if ( checkedFullscreen ) {
return;
}
if ( glConfig.isFullscreen ) {
checkedFullscreen = qtrue;
}
device = GetDeviceList();
sys_gl.numDevices = 0;
while( device && sys_gl.numDevices < MAX_DEVICES ) {
sys_gl.devices[ sys_gl.numDevices ] = device;
ri.Printf( PRINT_ALL, "Device : %d\n", sys_gl.numDevices);
CheckDeviceRenderers(device);
device = GetNextDevice(device);
sys_gl.numDevices++;
}
CheckErrors();
if ( sys_gl.textureMemory < 4000000 ) {
ri.Error( ERR_FATAL, "You must have at least four megs of video memory to play" );
}
if ( sys_gl.textureMemory < 16000000 ) {
sys_hardwareType = GLHW_RAGEPRO; // this will have to change with voodoo
} else {
sys_hardwareType = GLHW_GENERIC;
}
}
/*
=================
CreateGameWindow
=================
*/
static qboolean CreateGameWindow( void ) {
cvar_t *vid_xpos;
cvar_t *vid_ypos;
int mode;
int x, y;
Str255 pstr;
vid_xpos = ri.Cvar_Get( "vid_xpos", "30", 0 );
vid_ypos = ri.Cvar_Get( "vid_ypos", "30", 0 );
// get mode info
mode = r_mode->integer;
ri.Printf( PRINT_ALL, "...setting mode %d:", mode );
if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) {
ri.Printf( PRINT_ALL, " invalid mode\n" );
return false;
}
ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight );
/* Create window */
if ( r_fullscreen->integer ) {
int actualWidth, actualHeight;
// change display resolution
GLimp_ChangeDisplay( &actualWidth, &actualHeight );
x = ( actualWidth - glConfig.vidWidth ) / 2;
y = ( actualHeight - glConfig.vidHeight ) / 2;
sys_gl.drawable = (AGLDrawable) GetNewCWindow(kFullScreenWindow,nil,(WindowPtr)-1L);
} else {
x = vid_xpos->integer;
y = vid_ypos->integer;
sys_gl.drawable = (AGLDrawable) GetNewCWindow(kMainWindow,nil,(WindowPtr)-1L);
}
if( !sys_gl.drawable ) {
return qfalse;
}
SizeWindow((GrafPort *) sys_gl.drawable, glConfig.vidWidth, glConfig.vidHeight,GL_FALSE);
MoveWindow((GrafPort *) sys_gl.drawable,x, y, GL_FALSE);
ShowWindow((GrafPort *) sys_gl.drawable);
SetPort((GrafPort *) sys_gl.drawable);
CToPStr("Quake3: Arena", pstr);
SetWTitle((GrafPort *) sys_gl.drawable, pstr);
HiliteWindow((GrafPort *) sys_gl.drawable, 1);
return qtrue;
}
/*
===================
GLimp_SetMode
Returns false if the mode / fullscrenn / options combination failed,
so another fallback can be tried
===================
*/
qboolean GLimp_SetMode( void ) {
GLint value;
GLint attrib[64];
int i;
if ( !CreateGameWindow() ) {
ri.Printf( PRINT_ALL, "GLimp_Init: window could not be created" );
return qfalse;
}
// check devices now that the game has set the display mode,
// because RAVE devices don't get reported if in an 8 bit desktop
CheckDevices();
// set up the attribute list
i = 0;
attrib[i++] = AGL_RGBA;
attrib[i++] = AGL_DOUBLEBUFFER;
attrib[i++] = AGL_NO_RECOVERY;
attrib[i++] = AGL_ACCELERATED;
if ( r_colorbits->integer >= 16 ) {
attrib[i++] = AGL_RED_SIZE;
attrib[i++] = 8;
attrib[i++] = AGL_GREEN_SIZE;
attrib[i++] = 8;
attrib[i++] = AGL_BLUE_SIZE;
attrib[i++] = 8;
attrib[i++] = AGL_ALPHA_SIZE;
attrib[i++] = 0;
} else {
attrib[i++] = AGL_RED_SIZE;
attrib[i++] = 5;
attrib[i++] = AGL_GREEN_SIZE;
attrib[i++] = 5;
attrib[i++] = AGL_BLUE_SIZE;
attrib[i++] = 5;
attrib[i++] = AGL_ALPHA_SIZE;
attrib[i++] = 0;
}
attrib[i++] = AGL_STENCIL_SIZE;
if ( r_stencilbits->integer ) {
attrib[i++] = r_stencilbits->integer;
} else {
attrib[i++] = 0;
}
attrib[i++] = AGL_DEPTH_SIZE;
if ( r_depthbits->integer ) {
attrib[i++] = r_depthbits->integer;
} else {
attrib[i++] = 16;
}
attrib[i++] = 0;
/* Choose pixel format */
ri.Printf( PRINT_ALL, "aglChoosePixelFormat\n" );
if ( r_device->integer < 0 || r_device->integer >= sys_gl.numDevices ) {
ri.Cvar_Set( "r_device", "0" );
}
sys_gl.fmt = aglChoosePixelFormat( &sys_gl.devices[ r_device->integer ], 1, attrib);
if(!sys_gl.fmt) {
ri.Printf( PRINT_ALL, "GLimp_Init: Pixel format could not be achieved\n");
return qfalse;
}
ri.Printf( PRINT_ALL, "Selected pixel format 0x%x\n", (int)sys_gl.fmt );
aglDescribePixelFormat(sys_gl.fmt, AGL_RED_SIZE, &value);
glConfig.colorBits = value * 3;
aglDescribePixelFormat(sys_gl.fmt, AGL_STENCIL_SIZE, &value);
glConfig.stencilBits = value;
aglDescribePixelFormat(sys_gl.fmt, AGL_DEPTH_SIZE, &value);
glConfig.depthBits = value;
CheckErrors();
/* Create context */
sys_gl.context = aglCreateContext(sys_gl.fmt, NULL);
if(!sys_gl.context) {
ri.Printf( PRINT_ALL, "GLimp_init: Context could not be created\n");
return qfalse;
}
CheckErrors();
/* Make context current */
if(!aglSetDrawable(sys_gl.context, sys_gl.drawable)) {
ri.Printf( PRINT_ALL, "GLimp_Init: Could not attach to context\n" );
return qfalse;
}
CheckErrors();
if( !aglSetCurrentContext(sys_gl.context) ) {
ri.Printf( PRINT_ALL, "GLimp_Init: Could not attach to context");
return qfalse;
}
CheckErrors();
// check video memory and determine ragePro status
#if 0
if ( !GLimp_SufficientVideoMemory() ) {
return qfalse;
}
#endif
glConfig.hardwareType = sys_hardwareType; // FIXME: this isn't really right
// draw something to show that GL is alive
qglClearColor( 1, 0.5, 0.2, 0 );
qglClear( GL_COLOR_BUFFER_BIT );
GLimp_EndFrame();
CheckErrors();
// get the extensions
GLimp_Extensions();
CheckErrors();
return qtrue;
}
/*
===================
GLimp_Init
Don't return unless OpenGL has been properly initialized
===================
*/
void GLimp_Init( void ) {
GLint major, minor;
static qboolean registered;
ri.Printf( PRINT_ALL, "--- GLimp_Init ---\n" );
aglGetVersion( &major, &minor );
ri.Printf( PRINT_ALL, "aglVersion: %i.%i\n", (int)major, (int)minor );
r_device = ri.Cvar_Get( "r_device", "0", CVAR_LATCH | CVAR_ARCHIVE );
r_ext_transform_hint = ri.Cvar_Get( "r_ext_transform_hint", "1", CVAR_LATCH | CVAR_ARCHIVE );
if ( !registered ) {
ri.Cmd_AddCommand( "aglDescribe", GLimp_AglDescribe_f );
ri.Cmd_AddCommand( "aglState", GLimp_AglState_f );
}
memset( &glConfig, 0, sizeof( glConfig ) );
r_swapInterval->modified = qtrue; // force a set next frame
glConfig.deviceSupportsGamma = qtrue;
// FIXME: try for a voodoo first
sys_gl.systemGammas = GetSystemGammas();
if ( GLimp_SetMode() ) {
ri.Printf( PRINT_ALL, "------------------\n" );
return;
}
// fall back to the known-good mode
ri.Cvar_Set( "r_fullscreen", "1" );
ri.Cvar_Set( "r_mode", "3" );
ri.Cvar_Set( "r_stereo", "0" );
ri.Cvar_Set( "r_depthBits", "16" );
ri.Cvar_Set( "r_colorBits", "16" );
ri.Cvar_Set( "r_stencilBits", "0" );
if ( GLimp_SetMode() ) {
ri.Printf( PRINT_ALL, "------------------\n" );
return;
}
ri.Error( ERR_FATAL, "Could not initialize OpenGL" );
}
/*
===============
GLimp_EndFrame
===============
*/
void GLimp_EndFrame( void ) {
// check for variable changes
if ( r_swapInterval->modified ) {
r_swapInterval->modified = qfalse;
ri.Printf( PRINT_ALL, "Changing AGL_SWAP_INTERVAL\n" );
aglSetInteger( sys_gl.context, AGL_SWAP_INTERVAL, (long *)&r_swapInterval->integer );
}
// make sure the event loop is pumped
Sys_SendKeyEvents();
aglSwapBuffers( sys_gl.context );
}
/*
===============
GLimp_Shutdown
===============
*/
void GLimp_Shutdown( void ) {
if ( sys_gl.systemGammas ) {
RestoreSystemGammas( sys_gl.systemGammas );
DisposeSystemGammas( &sys_gl.systemGammas );
sys_gl.systemGammas = 0;
}
if ( sys_gl.context ) {
aglDestroyContext(sys_gl.context);
sys_gl.context = 0;
}
if ( sys_gl.fmt ) {
aglDestroyPixelFormat(sys_gl.fmt);
sys_gl.fmt = 0;
}
if ( sys_gl.drawable ) {
DisposeWindow((GrafPort *) sys_gl.drawable);
sys_gl.drawable = 0;
}
GLimp_ResetDisplay();
memset( &glConfig, 0, sizeof( glConfig ) );
}
void GLimp_LogComment( char *comment ) {
}
qboolean GLimp_SpawnRenderThread( void (*function)( void ) ) {
}
void *GLimp_RendererSleep( void ) {
}
void GLimp_FrontEndSleep( void ) {
}
void GLimp_WakeRenderer( void * data ) {
}
/*
===============
GLimp_SetGamma
===============
*/
void GLimp_SetGamma( unsigned char red[256],
unsigned char green[256],
unsigned char blue[256] ) {
char color[3][256];
int i;
for ( i = 0 ; i < 256 ; i++ ) {
color[0][i] = red[i];
color[1][i] = green[i];
color[2][i] = blue[i];
}
SetDeviceGammaRampGD( sys_gl.device, color[0] );
}

212
code/mac/mac_input.c Normal file
View File

@@ -0,0 +1,212 @@
#include "../client/client.h"
#include "mac_local.h"
#include "InputSprocket.h"
qboolean inputActive;
qboolean inputSuspended;
#define MAX_DEVICES 100
ISpDeviceReference devices[MAX_DEVICES];
ISpElementListReference elementList;
#define MAX_ELEMENTS 512
#define MAX_MOUSE_DEVICES 2
UInt32 numDevices;
UInt32 numElements[MAX_MOUSE_DEVICES];
ISpElementReference elements[MAX_MOUSE_DEVICES][MAX_ELEMENTS];
cvar_t *in_nomouse;
void Input_Init(void);
void Input_GetState( void );
/*
=================
Sys_InitInput
=================
*/
void Sys_InitInput( void ) {
NumVersion ver;
ISpElementInfo info;
int i, j;
OSStatus err;
// no input with dedicated servers
if ( com_dedicated->integer ) {
return;
}
Com_Printf( "------- Input Initialization -------\n" );
in_nomouse = Cvar_Get( "in_nomouse", "0", 0 );
if ( in_nomouse->integer != 0 ) {
Com_Printf( "in_nomouse is set, skipping.\n" );
Com_Printf( "------------------------------------\n" );
return;
}
ver = ISpGetVersion();
Com_Printf( "InputSprocket version: 0x%x\n", ver );
err = ISpStartup();
if ( err ) {
Com_Printf( "ISpStartup failed: %i\n", err );
Com_Printf( "------------------------------------\n" );
return;
}
// disable everything
ISpDevices_Extract( MAX_DEVICES, &numDevices, devices );
Com_Printf("%i total devices\n", numDevices);
if (numDevices > MAX_DEVICES) {
numDevices = MAX_DEVICES;
}
err = ISpDevices_Deactivate(
numDevices,
devices);
// enable mouse
err = ISpDevices_ExtractByClass(
kISpDeviceClass_Mouse,
MAX_DEVICES,
&numDevices,
devices);
Com_Printf("%i mouse devices\n", numDevices);
if (numDevices > MAX_MOUSE_DEVICES) {
numDevices = MAX_MOUSE_DEVICES;
}
err = ISpDevices_Activate( numDevices, devices);
for ( i = 0 ; i < numDevices ; i++ ) {
ISpDevice_GetElementList( devices[i], &elementList );
// ISpGetGlobalElementList( &elementList );
// go through all the elements and asign them Quake key codes
ISpElementList_Extract( elementList, MAX_ELEMENTS, &numElements[i], elements[i] );
Com_Printf("%i elements in list\n", numElements[i] );
for ( j = 0 ; j < numElements[i] ; j++ ) {
ISpElement_GetInfo( elements[i][j], &info );
PStringToCString( (char *)info.theString );
Com_Printf( "%i : %s\n", i, info.theString );
}
}
inputActive = true;
HideCursor();
Com_Printf( "------------------------------------\n" );
}
/*
=================
Sys_ShutdownInput
=================
*/
void Sys_ShutdownInput( void ) {
if ( !inputActive ) {
return;
}
ShowCursor();
ISpShutdown();
inputActive = qfalse;
}
void Sys_SuspendInput( void ) {
if ( inputSuspended ) {
return;
}
inputSuspended = true;
ShowCursor();
ISpSuspend();
}
void Sys_ResumeInput( void ) {
if ( !inputSuspended ) {
return;
}
inputSuspended = false;
HideCursor();
ISpResume();
}
/*
=================
Sys_Input
=================
*/
void Sys_Input( void ) {
ISpElementEvent event;
Boolean wasEvent;
UInt32 state, state2;
int xmove, ymove;
int button;
static int xtotal, ytotal;
int device;
if ( !inputActive ) {
return;
}
// during debugging it is sometimes usefull to be able to kill mouse support
if ( in_nomouse->integer ) {
Com_Printf( "Shutting down input.\n");
Sys_ShutdownInput();
return;
}
// always suspend for dedicated
if ( com_dedicated->integer ) {
Sys_SuspendInput();
return;
}
// temporarily deactivate if not in the game and
if ( cls.keyCatchers || cls.state != CA_ACTIVE ) {
if ( !glConfig.isFullscreen ) {
Sys_SuspendInput();
return;
}
}
Sys_ResumeInput();
// send all button events
for ( device = 0 ; device < numDevices ; device++ ) {
// mouse buttons
for ( button = 2 ; button < numElements[device] ; button++ ) {
while ( 1 ) {
ISpElement_GetNextEvent( elements[device][button], sizeof( event ), &event, &wasEvent );
if ( !wasEvent ) {
break;
}
if ( event.data ) {
Sys_QueEvent( 0, SE_KEY, K_MOUSE1 + button - 2, 1, 0, NULL );
} else {
Sys_QueEvent( 0, SE_KEY, K_MOUSE1 + button - 2, 0, 0, NULL );
}
}
}
// mouse movement
#define MAC_MOUSE_SCALE 163 // why this constant?
// send mouse event
ISpElement_GetSimpleState( elements[device][0], &state );
xmove = (int)state / MAC_MOUSE_SCALE;
ISpElement_GetSimpleState( elements[device][1], &state2 );
ymove = (int)state2 / -MAC_MOUSE_SCALE;
if ( xmove || ymove ) {
xtotal += xmove;
ytotal += ymove;
//Com_Printf("%i %i = %i %i\n", state, state2, xtotal, ytotal );
Sys_QueEvent( 0, SE_MOUSE, xmove, ymove, 0, NULL );
}
}
}

321
code/mac/mac_local.h Normal file
View File

@@ -0,0 +1,321 @@
/*
* Apple Universal Headers 3.1
*
* Uncomment any additional #includes you want to add to your MacHeaders.
*/
//#include <MacHeaders.h>
// #include <ADSP.h>
// #include <ADSPSecure.h>
#include <AEDataModel.h>
#include <AEObjects.h>
#include <AEPackObject.h>
#include <AERegistry.h>
#include <AEUserTermTypes.h>
// #include <AIFF.h>
#include <Aliases.h>
#include <Appearance.h>
#include <AppleEvents.h>
#include <AppleGuide.h>
#include <AppleScript.h>
#include <AppleTalk.h>
#include <ASDebugging.h>
#include <ASRegistry.h>
// #include <ATA.h>
// #include <AVComponents.h>
#include <Balloons.h>
// #include <CardServices.h>
// #include <CMAcceleration.h>
#include <CMApplication.h>
// #include <CMCalibrator.h>
// #include <CMComponent.h>
// #include <CMConversions.h>
#include <CMICCProfile.h>
// #include <CMMComponent.h>
// #include <CMPRComponent.h>
// #include <CMScriptingPlugin.h>
#include <CodeFragments.h>
// #include <Collections.h>
#include <ColorPicker.h>
// #include <ColorPickerComponents.h>
// #include <CommResources.h>
#include <Components.h>
#include <ConditionalMacros.h>
// #include <Connections.h>
// #include <ConnectionTools.h>
#include <Controls.h>
// #include <ControlStrip.h>
// #include <CRMSerialDevices.h>
// #include <CTBUtilities.h>
// #include <CursorDevices.h>
// #include <DatabaseAccess.h>
#include <DateTimeUtils.h>
// #include <Desk.h>
// #include <DeskBus.h>
#include <Devices.h>
#include <Dialogs.h>
// #include <Dictionary.h>
// #include <DigitalSignature.h>
#include <DiskInit.h>
// #include <Disks.h>
#include <Displays.h>
#include <Drag.h>
// #include <DrawSprocket.h>
// #include <DriverSynchronization.h>
#include <DriverFamilyMatching.h>
// #include <DriverGestalt.h>
// #include <DriverServices.h>
// #include <DriverSupport.h>
// #include <Editions.h>
// #include <Endian.h>
// #include <ENET.h>
#include <EPPC.h>
#include <Errors.h>
#include <Events.h>
// #include <fenv.h>
#include <Files.h>
// #include <FileTransfers.h>
// #include <FileTransferTools.h>
#include <FileTypesAndCreators.h>
#include <Finder.h>
#include <FinderRegistry.h>
#include <FixMath.h>
#include <Folders.h>
#include <Fonts.h>
// #include <fp.h>
// #include <FragLoad.h>
// #include <FSM.h>
#include <Gestalt.h>
// #include <GXEnvironment.h>
// #include <GXErrors.h>
// #include <GXFonts.h>
// #include <GXGraphics.h>
// #include <GXLayout.h>
// #include <GXMath.h>
// #include <GXMessages.h>
// #include <GXPrinterDrivers.h>
// #include <GXPrinting.h>
// #include <GXTypes.h>
// #include <GoggleSprocket.h>
#include <HFSVolumes.h>
// #include <HyperXCmd.h>
#include <Icons.h>
// #include <ImageCodec.h>
#include <ImageCompression.h>
// #include <InputSprocket.h>
// #include <Interrupts.h>
#include <IntlResources.h>
// #include <JManager.h>
// #include <Kernel.h>
// #include <Language.h>
#include <Lists.h>
// #include <LocationManager.h>
// #include <LocationManager.k.h>
#include <LowMem.h>
// #include <MachineExceptions.h>
#include <MacMemory.h>
// #include <MacTCP.h>
#include <MacTypes.h>
#include <MacWindows.h>
// #include <Math64.h>
// #include <MediaHandlers.h>
#include <Memory.h> // Start using MacMemory.h
#include <Menus.h>
// #include <MIDI.h>
#include <MixedMode.h>
#include <Movies.h>
// #include <MoviesFormat.h>
// #include <MP.h>
// #include <Multiprocessing.h>
#include <NameRegistry.h>
// #include <NetSprocket.h>
#include <Notification.h>
#include <NumberFormatting.h>
// #include <OCE.h>
// #include <OCEAuthDir.h>
// #include <OCEErrors.h>
// #include <OCEMail.h>
// #include <OCEMessaging.h>
// #include <OCEStandardDirectory.h>
// #include <OCEStandardMail.h>
// #include <OCETemplates.h>
#include <OSA.h>
#include <OSAComp.h>
#include <OSAGeneric.h>
#include <OSUtils.h>
// #include <Packages.h>
#include <Palettes.h>
#include <Patches.h>
// #include <PCCardAdapterPlugin.h>
// #include <PCCardEnablerPlugin.h>
// #include <PCCardTuples.h>
// #include <PCI.h>
// #include <PEFBinaryFormat.h>
// #include <PCCard.h>
// #include <Picker.h>
// #include <PictUtil.h>
// #include <PictUtils.h>
#include <PLStringFuncs.h>
// #include <Power.h>
#include <PPCToolbox.h>
#include <Printing.h>
#include <Processes.h>
// #include <QD3DAcceleration.h>
// #include <QD3DCamera.h>
// #include <QD3DController.h>
// #include <QD3DCustomElements.h>
// #include <QD3DDrawContext.h>
// #include <QD3DErrors.h>
// #include <QD3DExtension.h>
// #include <QD3DGeometry.h>
// #include <QD3DGroup.h>
// #include <QD3DIO.h>
// #include <QD3DLight.h>
// #include <QD3DMath.h>
// #include <QD3DPick.h>
// #include <QD3DRenderer.h>
// #include <QD3DSet.h>
// #include <QD3DShader.h>
// #include <QD3DStorage.h>
// #include <QD3DString.h>
// #include <QD3DStyle.h>
// #include <QD3DTransform.h>
// #include <QD3DView.h>
// #include <QD3DViewer.h>
// #include <QD3DWinViewer.h>
// #include <QD3D.h>
#include <QDOffscreen.h>
// #include <QTML.h>
// #include <QTMLCustomElements.h>
#include <Quickdraw.h>
#include <QuickdrawText.h>
// #include <QuickTimeComponents.h>
// #include <QuickTimeVR.h>
// #include <QuickTimeVRFormat.h>
// #include <RAVE.h>
// #include <QuickTimeMusic.h>
#include <Resources.h>
// #include <Retrace.h>
// #include <ROMDefs.h>
// #include <ScalerTypes.h>
// #include <ScalerStreamTypes.h>
#include <Scrap.h>
#include <Script.h>
// #include <SCSI.h>
#include <SegLoad.h>
// #include <Serial.h>
// #include <SFNTTypes.h>
// #include <SFNTLayoutTypes.h>
// #include <ShutDown.h>
// #include <SIOW.h>
// #include <Slots.h>
// #include <SocketServices.h>
#include <Sound.h>
// #include <SoundComponents.h>
// #include <SoundInput.h>
// #include <SoundSprocket.h>
// #include <Speech.h>
// #include <SpeechRecognition.h>
// #include <SpeechSynthesis.h>
#include <StandardFile.h>
#include <StringCompare.h>
// #include <Start.h>
#include <Strings.h> // Start using TextUtils.h
// #include <Telephones.h>
// #include <Terminals.h>
// #include <TerminalTools.h>
#include <TextCommon.h>
#include <TextEdit.h>
// #include <TextEncodingConverter.h>
// #include <TextServices.h>
#include <TextUtils.h>
#include <Threads.h>
#include <Timer.h>
#include <ToolUtils.h>
// #include <Translation.h>
// #include <TranslationExtensions.h>
#include <Traps.h>
// #include <TSMTE.h>
#include <Types.h> // Start using MacTypes.h
// #include <Unicode.h>
// #include <UnicodeConverter.h>
#include <Video.h>
// #include <VideoServices.h>
#include <Windows.h> // Start using MacWindows.h
// #include <WorldScript.h>
// #include <ZoomedVideo.h>
#include <gl.h>
#include <agl.h>
#include <console.h>
#include <SIOUX.h>
#include <math.h>
#include <time.h>
#include <errno.h>
#include <Profiler.h>
/* Menus: */
#define rMenuBar 128
/* Apple menu: */
#define mApple 128
#define iAbout 1
/* File menu: */
#define mFile 129
#define iQuit 1
/* Edit menu: */
#define mEdit 130
#define iUndo 1
#define iCut 3
#define iCopy 4
#define iPaste 5
#define iClear 6
/* Windows: */
#define kMainWindow 128
#define kFullScreenWindow 129
/* Dilogs: */
#define kAboutDialog 128
// mac_main.c
extern int sys_ticBase;
extern int sys_msecBase;
extern int sys_lastEventTic;
extern cvar_t *sys_waitNextEvent;
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
int PStringToCString( char *s );
int CStringToPString( char *s );
// mac_event.c
extern int vkeyToQuakeKey[256];
void Sys_SendKeyEvents (void);
// mac_net.c
void Sys_InitNetworking( void );
void Sys_ShutdownNetworking( void );
// mac_input.c
void Sys_InitInput( void );
void Sys_ShutdownInput( void );
void Sys_Input( void );
extern qboolean inputActive;
// mac_glimp.c
extern glconfig_t glConfig;
// mac_console.c
void Sys_InitConsole( void );
void Sys_ShowConsole( int level, qboolean quitOnClose );
void Sys_Print( const char *text );
char *Sys_ConsoleInput( void );
qboolean Sys_ConsoleEvent( EventRecord *event );

693
code/mac/mac_main.c Normal file
View File

@@ -0,0 +1,693 @@
#include "../client/client.h"
#include "mac_local.h"
#include <DriverServices.h>
#include <console.h>
/*
TODO:
about box
dir with no extension gives strange results
console input?
dedicated servers
icons
dynamic loading of server game
clipboard pasting
quit from menu
*/
int sys_ticBase;
int sys_msecBase;
int sys_lastEventTic;
cvar_t *sys_profile;
cvar_t *sys_waitNextEvent;
void putenv( char *buffer ) {
// the mac doesn't seem to have the concept of environment vars, so nop this
}
//===========================================================================
void Sys_UnloadGame (void) {
}
void *Sys_GetGameAPI (void *parms) {
void *GetGameAPI (void *import);
// we are hard-linked in, so no need to load anything
return GetGameAPI (parms);
}
void Sys_UnloadUI (void) {
}
void *Sys_GetUIAPI (void) {
void *GetUIAPI (void);
// we are hard-linked in, so no need to load anything
return GetUIAPI ();
}
void Sys_UnloadBotLib( void ) {
}
void *Sys_GetBotLibAPI (void *parms) {
return NULL;
}
void *Sys_GetBotAIAPI (void *parms) {
return NULL;
}
void dllEntry( int (*syscallptr)( int arg,... ) );
int vmMain( int command, ... );
void *Sys_LoadDll( const char *name, int (**entryPoint)(int, ...),
int (*systemCalls)(int, ...) ) {
dllEntry( systemCalls );
*entryPoint = vmMain;
return (void *)1;
}
void Sys_UnloadDll( void *dllHandle ) {
}
//===========================================================================
char *Sys_GetClipboardData( void ) { // FIXME
return NULL;
}
int Sys_GetProcessorId( void ) {
return CPUID_GENERIC;
}
void Sys_Mkdir( const char *path ) {
char ospath[MAX_OSPATH];
int err;
Com_sprintf( ospath, sizeof(ospath), "%s:", path );
err = mkdir( ospath, 0777 );
}
char *Sys_Cwd( void ) {
static char dir[MAX_OSPATH];
int l;
getcwd( dir, sizeof( dir ) );
dir[MAX_OSPATH-1] = 0;
// strip off the last colon
l = strlen( dir );
if ( l > 0 ) {
dir[ l - 1 ] = 0;
}
return dir;
}
char *Sys_DefaultCDPath( void ) {
return "";
}
char *Sys_DefaultBasePath( void ) {
return Sys_Cwd();
}
/*
=================================================================================
FILE FINDING
=================================================================================
*/
int PStringToCString( char *s ) {
int l;
int i;
l = ((unsigned char *)s)[0];
for ( i = 0 ; i < l ; i++ ) {
s[i] = s[i+1];
}
s[l] = 0;
return l;
}
int CStringToPString( char *s ) {
int l;
int i;
l = strlen( s );
for ( i = 0 ; i < l ; i++ ) {
s[l-i] = s[l-i-1];
}
s[0] = l;
return l;
}
#define MAX_FOUND_FILES 0x1000
char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs ) {
int nfiles;
char **listCopy;
char pdirectory[MAX_OSPATH];
char *list[MAX_FOUND_FILES];
int findhandle;
int directoryFlag;
int i;
int extensionLength;
int VRefNum;
int DrDirId;
int index;
FSSpec fsspec;
// get the volume and directory numbers
// there has to be a better way than this...
{
CInfoPBRec paramBlock;
Q_strncpyz( pdirectory, directory, sizeof(pdirectory) );
CStringToPString( pdirectory );
FSMakeFSSpec( 0, 0, (unsigned char *)pdirectory, &fsspec );
VRefNum = fsspec.vRefNum;
memset( &paramBlock, 0, sizeof( paramBlock ) );
paramBlock.hFileInfo.ioNamePtr = (unsigned char *)pdirectory;
PBGetCatInfoSync( &paramBlock );
DrDirId = paramBlock.hFileInfo.ioDirID;
}
if ( !extension) {
extension = "";
}
extensionLength = strlen( extension );
if ( wantsubs || (extension[0] == '/' && extension[1] == 0) ) {
directoryFlag = 16;
} else {
directoryFlag = 0;
}
nfiles = 0;
for ( index = 1 ; ; index++ ) {
CInfoPBRec paramBlock;
char fileName[MAX_OSPATH];
int length;
OSErr err;
memset( &paramBlock, 0, sizeof( paramBlock ) );
paramBlock.hFileInfo.ioNamePtr = (unsigned char *)fileName;
paramBlock.hFileInfo.ioVRefNum = VRefNum;
paramBlock.hFileInfo.ioFDirIndex = index;
paramBlock.hFileInfo.ioDirID = DrDirId;
err = PBGetCatInfoSync( &paramBlock );
if ( err != noErr ) {
break;
}
if ( directoryFlag ^ ( paramBlock.hFileInfo.ioFlAttrib & 16 ) ) {
continue;
}
// convert filename to C string
length = PStringToCString( fileName );
// check the extension
if ( !directoryFlag ) {
if ( length < extensionLength ) {
continue;
}
if ( Q_stricmp( fileName + length - extensionLength, extension ) ) {
continue;
}
}
// add this file
if ( nfiles == MAX_FOUND_FILES - 1 ) {
break;
}
list[ nfiles ] = CopyString( fileName );
nfiles++;
}
list[ nfiles ] = 0;
// return a copy of the list
*numfiles = nfiles;
if ( !nfiles ) {
return NULL;
}
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
for ( i = 0 ; i < nfiles ; i++ ) {
listCopy[i] = list[i];
}
listCopy[i] = NULL;
return listCopy;
}
void Sys_FreeFileList( char **list ) {
int i;
if ( !list ) {
return;
}
for ( i = 0 ; list[i] ; i++ ) {
Z_Free( list[i] );
}
Z_Free( list );
}
//===================================================================
/*
================
Sys_Init
The cvar and file system has been setup, so configurations are loaded
================
*/
void Sys_Init(void) {
Sys_InitNetworking();
Sys_InitInput();
}
/*
=================
Sys_Shutdown
=================
*/
void Sys_Shutdown( void ) {
Sys_EndProfiling();
Sys_ShutdownInput();
Sys_ShutdownNetworking();
}
/*
=================
Sys_BeginProfiling
=================
*/
static qboolean sys_profiling;
void Sys_BeginProfiling( void ) {
if ( !sys_profile->integer ) {
return;
}
ProfilerInit(collectDetailed, bestTimeBase, 16384, 64);
sys_profiling = qtrue;
}
/*
=================
Sys_EndProfiling
=================
*/
void Sys_EndProfiling( void ) {
unsigned char pstring[1024];
if ( !sys_profiling ) {
return;
}
sys_profiling = qfalse;
sprintf( (char *)pstring + 1, "%s:profile.txt", Cvar_VariableString( "fs_basepath" ) );
pstring[0] = strlen( (char *)pstring + 1 );
ProfilerDump( pstring );
ProfilerTerm();
}
//================================================================================
/*
================
Sys_Milliseconds
================
*/
int Sys_Milliseconds (void) {
#if 0
int c;
c = clock(); // FIXME, make more accurate
return c*1000/60;
#else
AbsoluteTime t;
Nanoseconds nano;
double doub;
#define kTwoPower32 (4294967296.0) /* 2^32 */
t = UpTime();
nano = AbsoluteToNanoseconds( t );
doub = (((double) nano.hi) * kTwoPower32) + nano.lo;
return doub * 0.000001;
#endif
}
/*
================
Sys_Error
================
*/
void Sys_Error( const char *error, ... ) {
va_list argptr;
char string[1024];
char string2[1024];
Sys_Shutdown();
va_start (argptr,error);
vsprintf (string2+1,error,argptr);
va_end (argptr);
string2[0] = strlen( string2 + 1 );
strcpy( string+1, "Quake 3 Error:" );
string[0] = strlen( string + 1 );
// set the dialog box strings
ParamText( (unsigned char *)string, (unsigned char *)string2,
(unsigned char *)string2, (unsigned char *)string2 );
// run a dialog
StopAlert( 128, NULL );
exit(0);
}
/*
================
Sys_Quit
================
*/
void Sys_Quit( void ) {
Sys_Shutdown();
exit (0);
}
//===================================================================
void Sys_BeginStreamedFile( fileHandle_t f, int readAhead ) {
}
void Sys_EndStreamedFile( fileHandle_t f ) {
}
int Sys_StreamedRead( void *buffer, int size, int count, fileHandle_t f ) {
return FS_Read( buffer, size, count, f );
}
void Sys_StreamSeek( fileHandle_t f, int offset, int origin ) {
FS_Seek( f, offset, origin );
}
//=================================================================================
/*
========================================================================
EVENT LOOP
========================================================================
*/
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message );
#define MAX_QUED_EVENTS 256
#define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 )
sysEvent_t eventQue[MAX_QUED_EVENTS];
int eventHead, eventTail;
byte sys_packetReceived[MAX_MSGLEN];
/*
================
Sys_QueEvent
A time of 0 will get the current time
Ptr should either be null, or point to a block of data that can
be freed by the game later.
================
*/
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr ) {
sysEvent_t *ev;
ev = &eventQue[ eventHead & MASK_QUED_EVENTS ];
if ( eventHead - eventTail >= MAX_QUED_EVENTS ) {
Com_Printf("Sys_QueEvent: overflow\n");
// we are discarding an event, but don't leak memory
if ( ev->evPtr ) {
free( ev->evPtr );
}
eventTail++;
}
eventHead++;
if ( time == 0 ) {
time = Sys_Milliseconds();
}
ev->evTime = time;
ev->evType = type;
ev->evValue = value;
ev->evValue2 = value2;
ev->evPtrLength = ptrLength;
ev->evPtr = ptr;
}
/*
=================
Sys_PumpEvents
=================
*/
void Sys_PumpEvents( void ) {
char *s;
msg_t netmsg;
netadr_t adr;
// pump the message loop
Sys_SendKeyEvents();
// check for console commands
s = Sys_ConsoleInput();
if ( s ) {
char *b;
int len;
len = strlen( s ) + 1;
b = malloc( len );
if ( !b ) {
Com_Error( ERR_FATAL, "malloc failed in Sys_PumpEvents" );
}
strcpy( b, s );
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b );
}
// check for other input devices
Sys_Input();
// check for network packets
MSG_Init( &netmsg, sys_packetReceived, sizeof( sys_packetReceived ) );
if ( Sys_GetPacket ( &adr, &netmsg ) ) {
netadr_t *buf;
int len;
// copy out to a seperate buffer for qeueing
len = sizeof( netadr_t ) + netmsg.cursize;
buf = malloc( len );
if ( !buf ) {
Com_Error( ERR_FATAL, "malloc failed in Sys_PumpEvents" );
}
*buf = adr;
memcpy( buf+1, netmsg.data, netmsg.cursize );
Sys_QueEvent( 0, SE_PACKET, 0, 0, len, buf );
}
}
/*
================
Sys_GetEvent
================
*/
sysEvent_t Sys_GetEvent( void ) {
sysEvent_t ev;
if ( eventHead == eventTail ) {
Sys_PumpEvents();
}
// return if we have data
if ( eventHead > eventTail ) {
eventTail++;
return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ];
}
// create an empty event to return
memset( &ev, 0, sizeof( ev ) );
ev.evTime = Sys_Milliseconds();
// track the mac event "when" to milliseconds rate
sys_ticBase = sys_lastEventTic;
sys_msecBase = ev.evTime;
return ev;
}
/*
=============
InitMacStuff
=============
*/
void InitMacStuff( void ) {
Handle menuBar;
char dir[MAX_OSPATH];
// init toolbox
MaxApplZone();
MoreMasters();
InitGraf(&qd.thePort);
InitFonts();
FlushEvents(everyEvent, 0);
SetEventMask( -1 );
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
// init menu
menuBar = GetNewMBar(rMenuBar);
if(!menuBar) {
Com_Error( ERR_FATAL, "MenuBar not found.");
}
SetMenuBar(menuBar);
DisposeHandle(menuBar);
AppendResMenu(GetMenuHandle(mApple),'DRVR');
DrawMenuBar();
Sys_InitConsole();
SetEventMask( -1 );
}
//==================================================================================
/*
=============
ReadCommandLineParms
Read startup options from a text file or dialog box
=============
*/
char *ReadCommandLineParms( void ) {
FILE *f;
int len;
char *buf;
EventRecord event;
// flush out all the events and see if shift is held down
// to bring up the args window
while ( WaitNextEvent(everyEvent, &event, 0, nil) ) {
}
if ( event.modifiers & 512 ) {
static char text[1024];
int argc;
char **argv;
int i;
argc = ccommand( &argv );
text[0] = 0;
// concat all the args into a string
// quote each arg seperately, because metrowerks does
// its own quote combining from the dialog
for ( i = 1 ; i < argc ; i++ ) {
if ( argv[i][0] != '+' ) {
Q_strcat( text, sizeof(text), "\"" );
}
Q_strcat( text, sizeof(text), argv[i] );
if ( argv[i][0] != '+' ) {
Q_strcat( text, sizeof(text), "\"" );
}
Q_strcat( text, sizeof(text), " " );
}
return text;
}
// otherwise check for a parms file
f = fopen( "MacQuake3Parms.txt", "r" );
if ( !f ) {
return "";
}
len = FS_filelength( f );
buf = malloc( len + 1 );
if ( !buf ) {
exit( 1 );
}
buf[len] = 0;
fread( buf, len, 1, f );
fclose( f );
return buf;
}
/*
=============
main
=============
*/
void main( void ) {
char *commandLine;
InitMacStuff();
commandLine = ReadCommandLineParms( );
Com_Init ( commandLine );
sys_profile = Cvar_Get( "sys_profile", "0", 0 );
sys_profile->modified = qfalse;
sys_waitNextEvent = Cvar_Get( "sys_waitNextEvent", "0", 0 );
while( 1 ) {
// run the frame
Com_Frame();
if ( sys_profile->modified ) {
sys_profile->modified = qfalse;
if ( sys_profile->integer ) {
Com_Printf( "Beginning profile.\n" );
Sys_BeginProfiling() ;
} else {
Com_Printf( "Ending profile.\n" );
Sys_EndProfiling();
}
}
}
}

527
code/mac/mac_net.c Normal file
View File

@@ -0,0 +1,527 @@
#include "../client/client.h"
#include "mac_local.h"
#include <OpenTransport.h>
#include <OpenTptInternet.h>
static qboolean gOTInited;
static EndpointRef endpoint = kOTInvalidEndpointRef;
static EndpointRef resolverEndpoint = kOTInvalidEndpointRef;
#define MAX_IPS 16
static int numIP;
static InetInterfaceInfo sys_inetInfo[MAX_IPS];
static TUDErr uderr;
void RcvUDErr( void ) {
memset( &uderr, 0, sizeof( uderr ) );
uderr.addr.maxlen = 0;
uderr.opt.maxlen = 0;
OTRcvUDErr( endpoint, &uderr );
}
void HandleOTError( int err, const char *func ) {
int r;
static int lastErr;
if ( err != lastErr ) {
Com_Printf( "%s: error %i\n", func, err );
}
// if we don't call OTLook, things wedge
r = OTLook( endpoint );
if ( err != lastErr ) {
Com_DPrintf( "%s: OTLook %i\n", func, r );
}
switch( r ) {
case T_UDERR:
RcvUDErr();
if ( err != lastErr ) {
Com_DPrintf( "%s: OTRcvUDErr %i\n", func, uderr.error );
}
break;
default:
// Com_Printf( "%s: Unknown OTLook error %i\n", func, r );
break;
}
lastErr = err; // don't spew tons of messages
}
/*
=================
NotifyProc
=================
*/
pascal void NotifyProc(void* contextPtr, OTEventCode code,
OTResult result, void* cookie) {
switch( code ) {
case T_OPENCOMPLETE:
endpoint = cookie;
break;
case T_UDERR:
RcvUDErr();
break;
}
}
/*
=================
GetFourByteOption
=================
*/
static OTResult GetFourByteOption(EndpointRef ep,
OTXTILevel level,
OTXTIName name,
UInt32 *value)
{
OTResult err;
TOption option;
TOptMgmt request;
TOptMgmt result;
/* Set up the option buffer */
option.len = kOTFourByteOptionSize;
option.level= level;
option.name = name;
option.status = 0;
option.value[0] = 0;// Ignored because we're getting the value.
/* Set up the request parameter for OTOptionManagement to point
to the option buffer we just filled out */
request.opt.buf= (UInt8 *) &option;
request.opt.len= sizeof(option);
request.flags= T_CURRENT;
/* Set up the reply parameter for OTOptionManagement. */
result.opt.buf = (UInt8 *) &option;
result.opt.maxlen = sizeof(option);
err = OTOptionManagement(ep, &request, &result);
if (err == noErr) {
switch (option.status)
{
case T_SUCCESS:
case T_READONLY:
*value = option.value[0];
break;
default:
err = option.status;
break;
}
}
return (err);
}
/*
=================
SetFourByteOption
=================
*/
static OTResult SetFourByteOption(EndpointRef ep,
OTXTILevel level,
OTXTIName name,
UInt32 value)
{
OTResult err;
TOption option;
TOptMgmt request;
TOptMgmt result;
/* Set up the option buffer to specify the option and value to
set. */
option.len = kOTFourByteOptionSize;
option.level= level;
option.name = name;
option.status = 0;
option.value[0] = value;
/* Set up request parameter for OTOptionManagement */
request.opt.buf= (UInt8 *) &option;
request.opt.len= sizeof(option);
request.flags = T_NEGOTIATE;
/* Set up reply parameter for OTOptionManagement. */
result.opt.buf = (UInt8 *) &option;
result.opt.maxlen = sizeof(option);
err = OTOptionManagement(ep, &request, &result);
if (err == noErr) {
if (option.status != T_SUCCESS)
err = option.status;
}
return (err);
}
/*
=====================
NET_GetLocalAddress
=====================
*/
void NET_GetLocalAddress( void ) {
OSStatus err;
for ( numIP = 0 ; numIP < MAX_IPS ; numIP++ ) {
err = OTInetGetInterfaceInfo( &sys_inetInfo[ numIP ], numIP );
if ( err ) {
break;
}
Com_Printf( "LocalAddress: %i.%i.%i.%i\n",
((byte *)&sys_inetInfo[numIP].fAddress)[0],
((byte *)&sys_inetInfo[numIP].fAddress)[1],
((byte *)&sys_inetInfo[numIP].fAddress)[2],
((byte *)&sys_inetInfo[numIP].fAddress)[3] );
Com_Printf( "Netmask: %i.%i.%i.%i\n",
((byte *)&sys_inetInfo[numIP].fNetmask)[0],
((byte *)&sys_inetInfo[numIP].fNetmask)[1],
((byte *)&sys_inetInfo[numIP].fNetmask)[2],
((byte *)&sys_inetInfo[numIP].fNetmask)[3] );
}
}
/*
==================
Sys_InitNetworking
struct InetAddress
{
OTAddressType fAddressType; // always AF_INET
InetPort fPort; // Port number
InetHost fHost; // Host address in net byte order
UInt8 fUnused[8]; // Traditional unused bytes
};
typedef struct InetAddress InetAddress;
==================
*/
void Sys_InitNetworking( void ) {
OSStatus err;
OTConfiguration *config;
TBind bind, bindOut;
InetAddress in, out;
int i;
Com_Printf( "----- Sys_InitNetworking -----\n" );
// init OpenTransport
Com_Printf( "... InitOpenTransport()\n" );
err = InitOpenTransport();
if ( err != noErr ) {
Com_Printf( "InitOpenTransport() failed\n" );
Com_Printf( "------------------------------\n" );
return;
}
gOTInited = true;
// get an endpoint
Com_Printf( "... OTOpenEndpoint()\n" );
config = OTCreateConfiguration( kUDPName );
#if 1
endpoint = OTOpenEndpoint( config, 0, nil, &err);
#else
err = OTAsyncOpenEndpoint( config, 0, 0, NotifyProc, 0 );
if ( !endpoint ) {
err = 1;
}
#endif
if ( err != noErr ) {
endpoint = 0;
Com_Printf( "OTOpenEndpoint() failed\n" );
Com_Printf( "------------------------------\n" );
return;
}
// set non-blocking
err = OTSetNonBlocking( endpoint );
// scan for a valid port in our range
Com_Printf( "... OTBind()\n" );
for ( i = 0 ; i < 10 ; i++ ) {
in.fAddressType = AF_INET;
in.fPort = PORT_SERVER + i;
in.fHost = 0;
bind.addr.maxlen = sizeof( in );
bind.addr.len = sizeof( in );
bind.addr.buf = (unsigned char *)&in;
bind.qlen = 0;
bindOut.addr.maxlen = sizeof( out );
bindOut.addr.len = sizeof( out );
bindOut.addr.buf = (unsigned char *)&out;
bindOut.qlen = 0;
err = OTBind( endpoint, &bind, &bindOut );
if ( err == noErr ) {
Com_Printf( "Opened UDP endpoint at port %i\n",
out.fPort );
break;
}
}
if ( err != noErr ) {
Com_Printf( "Couldn't bind a local port\n" );
}
// get the local address for LAN client detection
NET_GetLocalAddress();
// set to allow broadcasts
err = SetFourByteOption( endpoint, INET_IP, IP_BROADCAST, T_YES );
if ( err != noErr ) {
Com_Printf( "IP_BROADCAST failed\n" );
}
// get an endpoint just for resolving addresses, because
// I was having crashing problems doing it on the same endpoint
config = OTCreateConfiguration( kUDPName );
resolverEndpoint = OTOpenEndpoint( config, 0, nil, &err);
if ( err != noErr ) {
resolverEndpoint = 0;
Com_Printf( "OTOpenEndpoint() for resolver failed\n" );
Com_Printf( "------------------------------\n" );
return;
}
in.fAddressType = AF_INET;
in.fPort = 0;
in.fHost = 0;
bind.addr.maxlen = sizeof( in );
bind.addr.len = sizeof( in );
bind.addr.buf = (unsigned char *)&in;
bind.qlen = 0;
bindOut.addr.maxlen = sizeof( out );
bindOut.addr.len = sizeof( out );
bindOut.addr.buf = (unsigned char *)&out;
bindOut.qlen = 0;
err = OTBind( resolverEndpoint, &bind, &bindOut );
Com_Printf( "------------------------------\n" );
}
/*
==================
Sys_ShutdownNetworking
==================
*/
void Sys_ShutdownNetworking( void ) {
Com_Printf( "Sys_ShutdownNetworking();\n" );
if ( endpoint != kOTInvalidEndpointRef ) {
OTUnbind( endpoint );
OTCloseProvider( endpoint );
endpoint = kOTInvalidEndpointRef;
}
if ( resolverEndpoint != kOTInvalidEndpointRef ) {
OTUnbind( resolverEndpoint );
OTCloseProvider( resolverEndpoint );
resolverEndpoint = kOTInvalidEndpointRef;
}
if (gOTInited) {
CloseOpenTransport();
gOTInited = false;
}
}
/*
=============
Sys_StringToAdr
Does NOT parse port numbers
idnewt
192.246.40.70
=============
*/
qboolean Sys_StringToAdr( const char *s, netadr_t *a ) {
OSStatus err;
TBind in, out;
InetAddress inAddr;
DNSAddress dnsAddr;
if ( !resolverEndpoint ) {
return qfalse;
}
memset( &in, 0, sizeof( in ) );
in.addr.buf = (UInt8 *) &dnsAddr;
in.addr.len = OTInitDNSAddress(&dnsAddr, (char *)s );
in.qlen = 0;
memset( &out, 0, sizeof( out ) );
out.addr.buf = (byte *)&inAddr;
out.addr.maxlen = sizeof( inAddr );
out.qlen = 0;
err = OTResolveAddress( resolverEndpoint, &in, &out, 10000 );
if ( err ) {
HandleOTError( err, "Sys_StringToAdr" );
return qfalse;
}
a->type = NA_IP;
*(int *)a->ip = inAddr.fHost;
return qtrue;
}
/*
==================
Sys_SendPacket
==================
*/
#define MAX_PACKETLEN 1400
void Sys_SendPacket( int length, const void *data, netadr_t to ) {
TUnitData d;
InetAddress inAddr;
OSStatus err;
if ( !endpoint ) {
return;
}
if ( length > MAX_PACKETLEN ) {
Com_Error( ERR_DROP, "Sys_SendPacket: length > MAX_PACKETLEN" );
}
inAddr.fAddressType = AF_INET;
inAddr.fPort = to.port;
if ( to.type == NA_BROADCAST ) {
inAddr.fHost = -1;
} else {
inAddr.fHost = *(int *)&to.ip;
}
memset( &d, 0, sizeof( d ) );
d.addr.len = sizeof( inAddr );
d.addr.maxlen = sizeof( inAddr );
d.addr.buf = (unsigned char *)&inAddr;
d.opt.len = 0;
d.opt.maxlen = 0;
d.opt.buf = NULL;
d.udata.len = length;
d.udata.maxlen = length;
d.udata.buf = (unsigned char *)data;
err = OTSndUData( endpoint, &d );
if ( err ) {
HandleOTError( err, "Sys_SendPacket" );
}
}
/*
==================
Sys_GetPacket
Never called by the game logic, just the system event queing
==================
*/
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message ) {
TUnitData d;
InetAddress inAddr;
OSStatus err;
OTFlags flags;
if ( !endpoint ) {
return qfalse;
}
inAddr.fAddressType = AF_INET;
inAddr.fPort = 0;
inAddr.fHost = 0;
memset( &d, 0, sizeof( d ) );
d.addr.len = sizeof( inAddr );
d.addr.maxlen = sizeof( inAddr );
d.addr.buf = (unsigned char *)&inAddr;
d.opt.len = 0;
d.opt.maxlen = 0;
d.opt.buf = 0;
d.udata.len = net_message->maxsize;
d.udata.maxlen = net_message->maxsize;
d.udata.buf = net_message->data;
err = OTRcvUData( endpoint, &d, &flags );
if ( err ) {
if ( err == kOTNoDataErr ) {
return false;
}
HandleOTError( err, "Sys_GetPacket" );
return qfalse;
}
net_from->type = NA_IP;
net_from->port = inAddr.fPort;
*(int *)net_from->ip = inAddr.fHost;
net_message->cursize = d.udata.len;
return qtrue;
}
/*
==================
Sys_IsLANAddress
LAN clients will have their rate var ignored
==================
*/
qboolean Sys_IsLANAddress (netadr_t adr) {
int i;
int ip;
if ( adr.type == NA_LOOPBACK ) {
return qtrue;
}
if ( adr.type != NA_IP ) {
return qfalse;
}
for ( ip = 0 ; ip < numIP ; ip++ ) {
for ( i = 0 ; i < 4 ; i++ ) {
if ( ( adr.ip[i] & ((byte *)&sys_inetInfo[ip].fNetmask)[i] )
!= ( ((byte *)&sys_inetInfo[ip].fAddress)[i] & ((byte *)&sys_inetInfo[ip].fNetmask)[i] ) ) {
break;
}
}
if ( i == 4 ) {
return qtrue; // matches this subnet
}
}
return qfalse;
}
void NET_Sleep( int i ) {
}

140
code/mac/mac_snddma.c Normal file
View File

@@ -0,0 +1,140 @@
// mac_snddma.c
// all other sound mixing is portable
#include "../client/snd_local.h"
#include <sound.h>
#define MAX_MIXED_SAMPLES 0x8000
#define SUBMISSION_CHUNK 0x100
static short s_mixedSamples[MAX_MIXED_SAMPLES];
static int s_chunkCount; // number of chunks submitted
static SndChannel *s_sndChan;
static ExtSoundHeader s_sndHeader;
/*
===============
S_Callback
===============
*/
void S_Callback( SndChannel *sc, SndCommand *cmd ) {
SndCommand mySndCmd;
SndCommand mySndCmd2;
int offset;
offset = ( s_chunkCount * SUBMISSION_CHUNK ) & (MAX_MIXED_SAMPLES-1);
// queue up another sound buffer
memset( &s_sndHeader, 0, sizeof( s_sndHeader ) );
s_sndHeader.samplePtr = (void *)(s_mixedSamples + offset);
s_sndHeader.numChannels = 2;
s_sndHeader.sampleRate = rate22khz;
s_sndHeader.loopStart = 0;
s_sndHeader.loopEnd = 0;
s_sndHeader.encode = extSH;
s_sndHeader.baseFrequency = 1;
s_sndHeader.numFrames = SUBMISSION_CHUNK / 2;
s_sndHeader.markerChunk = NULL;
s_sndHeader.instrumentChunks = NULL;
s_sndHeader.AESRecording = NULL;
s_sndHeader.sampleSize = 16;
mySndCmd.cmd = bufferCmd;
mySndCmd.param1 = 0;
mySndCmd.param2 = (int)&s_sndHeader;
SndDoCommand( sc, &mySndCmd, true );
// and another callback
mySndCmd2.cmd = callBackCmd;
mySndCmd2.param1 = 0;
mySndCmd2.param2 = 0;
SndDoCommand( sc, &mySndCmd2, true );
s_chunkCount++; // this is the next buffer we will submit
}
/*
===============
S_MakeTestPattern
===============
*/
void S_MakeTestPattern( void ) {
int i;
float v;
int sample;
for ( i = 0 ; i < dma.samples / 2 ; i ++ ) {
v = sin( M_PI * 2 * i / 64 );
sample = v * 0x4000;
((short *)dma.buffer)[i*2] = sample;
((short *)dma.buffer)[i*2+1] = sample;
}
}
/*
===============
SNDDMA_Init
===============
*/
qboolean SNDDMA_Init(void) {
int err;
// create a sound channel
s_sndChan = NULL;
err = SndNewChannel( &s_sndChan, sampledSynth, initStereo, NewSndCallBackProc(S_Callback) );
if ( err ) {
return false;
}
dma.channels = 2;
dma.samples = MAX_MIXED_SAMPLES;
dma.submission_chunk = SUBMISSION_CHUNK;
dma.samplebits = 16;
dma.speed = 22050;
dma.buffer = (byte *)s_mixedSamples;
// que up the first submission-chunk sized buffer
s_chunkCount = 0;
S_Callback( s_sndChan, NULL );
return qtrue;
}
/*
===============
SNDDMA_GetDMAPos
===============
*/
int SNDDMA_GetDMAPos(void) {
return s_chunkCount * SUBMISSION_CHUNK;
}
/*
===============
SNDDMA_Shutdown
===============
*/
void SNDDMA_Shutdown(void) {
if ( s_sndChan ) {
SndDisposeChannel( s_sndChan, true );
s_sndChan = NULL;
}
}
/*
===============
SNDDMA_BeginPainting
===============
*/
void SNDDMA_BeginPainting(void) {
}
/*
===============
SNDDMA_Submit
===============
*/
void SNDDMA_Submit(void) {
}

3
code/mac/macprefix.h Normal file
View File

@@ -0,0 +1,3 @@
//#define __MACOS__ // needed for MrC
#define BOTLIB

0
code/mac/q3.rsrc Normal file
View File