Initial commit.
This commit is contained in:
487
code/mac/MacGamma.c
Normal file
487
code/mac/MacGamma.c
Normal 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
474
code/mac/MacGamma.cpp
Normal 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
82
code/mac/MacGamma.h
Normal 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
BIN
code/mac/MacQuake3
Normal file
Binary file not shown.
119
code/mac/mac_console.c
Normal file
119
code/mac/mac_console.c
Normal 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
357
code/mac/mac_event.c
Normal 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
829
code/mac/mac_glimp.c
Normal 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
212
code/mac/mac_input.c
Normal 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
321
code/mac/mac_local.h
Normal 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
693
code/mac/mac_main.c
Normal 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( ¶mBlock, 0, sizeof( paramBlock ) );
|
||||
paramBlock.hFileInfo.ioNamePtr = (unsigned char *)pdirectory;
|
||||
PBGetCatInfoSync( ¶mBlock );
|
||||
|
||||
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( ¶mBlock, 0, sizeof( paramBlock ) );
|
||||
paramBlock.hFileInfo.ioNamePtr = (unsigned char *)fileName;
|
||||
paramBlock.hFileInfo.ioVRefNum = VRefNum;
|
||||
paramBlock.hFileInfo.ioFDirIndex = index;
|
||||
paramBlock.hFileInfo.ioDirID = DrDirId;
|
||||
|
||||
err = PBGetCatInfoSync( ¶mBlock );
|
||||
|
||||
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
527
code/mac/mac_net.c
Normal 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 *)∈
|
||||
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 *)∈
|
||||
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
140
code/mac/mac_snddma.c
Normal 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
3
code/mac/macprefix.h
Normal file
@@ -0,0 +1,3 @@
|
||||
//#define __MACOS__ // needed for MrC
|
||||
#define BOTLIB
|
||||
|
||||
0
code/mac/q3.rsrc
Normal file
0
code/mac/q3.rsrc
Normal file
Reference in New Issue
Block a user