Initial commit.
This commit is contained in:
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user