Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 40342a9e36
1335 lines (1061 sloc) 29.732 kB
/*
===========================================================================
Wolfenstein: Enemy Territory GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Wolfenstein: Enemy Territory GPL Source Code (“Wolf ET Source Code”).
Wolf ET Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Wolf ET Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wolf ET Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Wolf: ET Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Wolf ET Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
// win_main.h
#include "../client/client.h"
#include "../qcommon/qcommon.h"
#include "win_local.h"
#include "resource.h"
#include <errno.h>
#include <float.h>
#include <fcntl.h>
#include <stdio.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
#define CD_BASEDIR "et"
#define CD_EXE "et.exe"
#define CD_BASEDIR_LINUX "bin\\x86\\glibc-2.1"
#define CD_EXE_LINUX "et"
#define MEM_THRESHOLD 96 * 1024 * 1024
static char sys_cmdline[MAX_STRING_CHARS];
/*
==================
Sys_LowPhysicalMemory()
==================
*/
qboolean Sys_LowPhysicalMemory() {
MEMORYSTATUS stat;
GlobalMemoryStatus( &stat );
return ( stat.dwTotalPhys <= MEM_THRESHOLD ) ? qtrue : qfalse;
}
/*
==================
Sys_StartProcess
NERVE - SMF
==================
*/
void Sys_StartProcess( char *exeName, qboolean doexit ) {
TCHAR szPathOrig[_MAX_PATH];
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof( si ) );
si.cb = sizeof( si );
GetCurrentDirectory( _MAX_PATH, szPathOrig );
// JPW NERVE swiped from Sherman's SP code
if ( !CreateProcess( NULL, va( "%s\\%s", szPathOrig, exeName ), NULL, NULL,FALSE, 0, NULL, NULL, &si, &pi ) ) {
// couldn't start it, popup error box
Com_Error( ERR_DROP, "Could not start process: '%s\\%s' ", szPathOrig, exeName );
return;
}
// jpw
// TTimo: similar way of exiting as used in Sys_OpenURL below
if ( doexit ) {
Cbuf_ExecuteText( EXEC_APPEND, "quit\n" );
}
}
/*
==================
Sys_OpenURL
NERVE - SMF
==================
*/
void Sys_OpenURL( const char *url, qboolean doexit ) {
HWND wnd;
static qboolean doexit_spamguard = qfalse;
if ( doexit_spamguard ) {
Com_DPrintf( "Sys_OpenURL: already in a doexit sequence, ignoring %s\n", url );
return;
}
Com_Printf( "Open URL: %s\n", url );
if ( !ShellExecute( NULL, "open", url, NULL, NULL, SW_RESTORE ) ) {
// couldn't start it, popup error box
Com_Error( ERR_DROP, "Could not open url: '%s' ", url );
return;
}
wnd = GetForegroundWindow();
if ( wnd ) {
ShowWindow( wnd, SW_MAXIMIZE );
}
if ( doexit ) {
// show_bug.cgi?id=612
doexit_spamguard = qtrue;
Cbuf_ExecuteText( EXEC_APPEND, "quit\n" );
}
}
/*
==================
Sys_BeginProfiling
==================
*/
void Sys_BeginProfiling( void ) {
// this is just used on the mac build
}
/*
=============
Sys_Error
Show the early console as an error dialog
=============
*/
void QDECL Sys_Error( const char *error, ... ) {
va_list argptr;
char text[4096];
MSG msg;
va_start( argptr, error );
Q_vsnprintf( text, sizeof( text ), error, argptr );
va_end( argptr );
Conbuf_AppendText( text );
Conbuf_AppendText( "\n" );
Sys_SetErrorText( text );
Sys_ShowConsole( 1, qtrue );
timeEndPeriod( 1 );
IN_Shutdown();
// wait for the user to quit
while ( 1 ) {
if ( !GetMessage( &msg, NULL, 0, 0 ) ) {
Com_Quit_f();
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
Sys_DestroyConsole();
exit( 1 );
}
/*
==============
Sys_Quit
==============
*/
void Sys_Quit( void ) {
timeEndPeriod( 1 );
IN_Shutdown();
Sys_DestroyConsole();
exit( 0 );
}
/*
==============
Sys_Print
==============
*/
void Sys_Print( const char *msg ) {
Conbuf_AppendText( msg );
}
/*
==============
Sys_Mkdir
==============
*/
void Sys_Mkdir( const char *path ) {
_mkdir( path );
}
/*
==============
Sys_Cwd
==============
*/
char *Sys_Cwd( void ) {
static char cwd[MAX_OSPATH];
_getcwd( cwd, sizeof( cwd ) - 1 );
cwd[MAX_OSPATH - 1] = 0;
return cwd;
}
/*
==============
Sys_DefaultCDPath
==============
*/
char *Sys_DefaultCDPath( void ) {
return "";
}
/*
==============
Sys_DefaultBasePath
==============
*/
char *Sys_DefaultBasePath( void ) {
return Sys_Cwd();
}
/*
==============================================================
DIRECTORY SCANNING
==============================================================
*/
#define MAX_FOUND_FILES 0x1000
void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) {
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
char filename[MAX_OSPATH];
int findhandle;
struct _finddata_t findinfo;
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
return;
}
if ( strlen( subdirs ) ) {
Com_sprintf( search, sizeof( search ), "%s\\%s\\*", basedir, subdirs );
} else {
Com_sprintf( search, sizeof( search ), "%s\\*", basedir );
}
findhandle = _findfirst( search, &findinfo );
if ( findhandle == -1 ) {
return;
}
do {
if ( findinfo.attrib & _A_SUBDIR ) {
if ( Q_stricmp( findinfo.name, "." ) && Q_stricmp( findinfo.name, ".." ) ) {
if ( strlen( subdirs ) ) {
Com_sprintf( newsubdirs, sizeof( newsubdirs ), "%s\\%s", subdirs, findinfo.name );
} else {
Com_sprintf( newsubdirs, sizeof( newsubdirs ), "%s", findinfo.name );
}
Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
}
}
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
break;
}
Com_sprintf( filename, sizeof( filename ), "%s\\%s", subdirs, findinfo.name );
if ( !Com_FilterPath( filter, filename, qfalse ) ) {
continue;
}
list[ *numfiles ] = CopyString( filename );
( *numfiles )++;
} while ( _findnext( findhandle, &findinfo ) != -1 );
_findclose( findhandle );
}
static qboolean strgtr( const char *s0, const char *s1 ) {
int l0, l1, i;
l0 = strlen( s0 );
l1 = strlen( s1 );
if ( l1 < l0 ) {
l0 = l1;
}
for ( i = 0; i < l0; i++ ) {
if ( s1[i] > s0[i] ) {
return qtrue;
}
if ( s1[i] < s0[i] ) {
return qfalse;
}
}
return qfalse;
}
char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs ) {
char search[MAX_OSPATH];
int nfiles;
char **listCopy;
char *list[MAX_FOUND_FILES];
struct _finddata_t findinfo;
int findhandle;
int flag;
int i;
if ( filter ) {
nfiles = 0;
Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
list[ nfiles ] = 0;
*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;
}
if ( !extension ) {
extension = "";
}
// passing a slash as extension will find directories
if ( extension[0] == '/' && extension[1] == 0 ) {
extension = "";
flag = 0;
} else {
flag = _A_SUBDIR;
}
Com_sprintf( search, sizeof( search ), "%s\\*%s", directory, extension );
// search
nfiles = 0;
findhandle = _findfirst( search, &findinfo );
if ( findhandle == -1 ) {
*numfiles = 0;
return NULL;
}
do {
if ( ( !wantsubs && flag ^ ( findinfo.attrib & _A_SUBDIR ) ) || ( wantsubs && findinfo.attrib & _A_SUBDIR ) ) {
if ( nfiles == MAX_FOUND_FILES - 1 ) {
break;
}
list[ nfiles ] = CopyString( findinfo.name );
nfiles++;
}
} while ( _findnext( findhandle, &findinfo ) != -1 );
list[ nfiles ] = 0;
_findclose( findhandle );
// 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;
do {
flag = 0;
for ( i = 1; i < nfiles; i++ ) {
if ( strgtr( listCopy[i - 1], listCopy[i] ) ) {
char *temp = listCopy[i];
listCopy[i] = listCopy[i - 1];
listCopy[i - 1] = temp;
flag = 1;
}
}
} while ( flag );
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_ScanForCD
Search all the drives to see if there is a valid CD to grab
the cddir from
================
*/
qboolean Sys_ScanForCD( void ) {
static char cddir[MAX_OSPATH];
char drive[4];
FILE *f;
char test[MAX_OSPATH];
#if 0
// don't override a cdpath on the command line
if ( strstr( sys_cmdline, "cdpath" ) ) {
return;
}
#endif
drive[0] = 'c';
drive[1] = ':';
drive[2] = '\\';
drive[3] = 0;
// scan the drives
for ( drive[0] = 'c' ; drive[0] <= 'z' ; drive[0]++ ) {
if ( GetDriveType( drive ) != DRIVE_CDROM ) {
continue;
}
sprintf( cddir, "%s%s", drive, CD_BASEDIR );
sprintf( test, "%s\\%s", cddir, CD_EXE );
f = fopen( test, "r" );
if ( f ) {
fclose( f );
return qtrue;
} else {
sprintf( cddir, "%s%s", drive, CD_BASEDIR_LINUX );
sprintf( test, "%s\\%s", cddir, CD_EXE_LINUX );
f = fopen( test, "r" );
if ( f ) {
fclose( f );
return qtrue;
}
}
}
return qfalse;
}
/*
================
Sys_CheckCD
Return true if the proper CD is in the drive
================
*/
qboolean Sys_CheckCD( void ) {
// FIXME: mission pack
return qtrue;
//return Sys_ScanForCD();
}
/*
================
Sys_GetClipboardData
================
*/
char *Sys_GetClipboardData( void ) {
char *data = NULL;
char *cliptext;
if ( OpenClipboard( NULL ) != 0 ) {
HANDLE hClipboardData;
if ( ( hClipboardData = GetClipboardData( CF_TEXT ) ) != 0 ) {
if ( ( cliptext = GlobalLock( hClipboardData ) ) != 0 ) {
data = Z_Malloc( GlobalSize( hClipboardData ) + 1 );
Q_strncpyz( data, cliptext, GlobalSize( hClipboardData ) );
GlobalUnlock( hClipboardData );
strtok( data, "\n\r\b" );
}
}
CloseClipboard();
}
return data;
}
/*
========================================================================
LOAD/UNLOAD DLL
========================================================================
*/
/*
=================
Sys_UnloadDll
=================
*/
void Sys_UnloadDll( void *dllHandle ) {
if ( !dllHandle ) {
return;
}
if ( !FreeLibrary( dllHandle ) ) {
Com_Error( ERR_FATAL, "Sys_UnloadDll FreeLibrary failed" );
}
}
/*
=================
Sys_LoadDll
Used to load a development dll instead of a virtual machine
=================
*/
extern int cl_connectedToPureServer;
char* Sys_GetDLLName( const char *name ) {
return va( "%s_mp_x86.dll", name );
}
// fqpath param added 2/15/02 by T.Ray - Sys_LoadDll is only called in vm.c at this time
// fqpath will be empty if dll not loaded, otherwise will hold fully qualified path of dll module loaded
// fqpath buffersize must be at least MAX_QPATH+1 bytes long
void * QDECL Sys_LoadDll( const char *name, char *fqpath, int( QDECL **entryPoint ) ( int, ... ),
int ( QDECL *systemcalls )( int, ... ) ) {
HINSTANCE libHandle;
void ( QDECL * dllEntry )( int ( QDECL *syscallptr )( int, ... ) );
char *basepath;
char *cdpath;
char *gamedir;
char *fn;
char filename[MAX_QPATH];
*fqpath = 0 ; // added 2/15/02 by T.Ray
Q_strncpyz( filename, Sys_GetDLLName( name ), sizeof( filename ) );
basepath = Cvar_VariableString( "fs_basepath" );
cdpath = Cvar_VariableString( "fs_cdpath" );
gamedir = Cvar_VariableString( "fs_game" );
// try gamepath first
fn = FS_BuildOSPath( basepath, gamedir, filename );
// TTimo - this is only relevant for full client
// if a full client runs a dedicated server, it's not affected by this
#if !defined( DEDICATED )
// NERVE - SMF - extract dlls from pak file for security
// we have to handle the game dll a little differently
// TTimo - passing the exact path to check against
// (compatibility with other OSes loading procedure)
if ( cl_connectedToPureServer && Q_strncmp( name, "qagame", 6 ) ) {
if ( !FS_CL_ExtractFromPakFile( fn, gamedir, filename, NULL ) ) {
Com_Error( ERR_DROP, "Game code(%s) failed Pure Server check", filename );
}
}
#endif
libHandle = LoadLibrary( fn );
if ( !libHandle ) {
// First try falling back to BASEGAME
fn = FS_BuildOSPath( basepath, BASEGAME, filename );
libHandle = LoadLibrary( fn );
if ( !libHandle ) {
// Final fall-back to current directory
libHandle = LoadLibrary( filename );
if ( !libHandle ) {
return NULL;
}
Q_strncpyz( fqpath, filename, MAX_QPATH ) ; // added 2/15/02 by T.Ray
} else {Q_strncpyz( fqpath, fn, MAX_QPATH ) ; // added 2/15/02 by T.Ray
}
} else {Q_strncpyz( fqpath, fn, MAX_QPATH ) ; // added 2/15/02 by T.Ray
}
dllEntry = ( void ( QDECL * )( int ( QDECL * )( int, ... ) ) )GetProcAddress( libHandle, "dllEntry" );
*entryPoint = ( int ( QDECL * )( int,... ) )GetProcAddress( libHandle, "vmMain" );
if ( !*entryPoint || !dllEntry ) {
FreeLibrary( libHandle );
return NULL;
}
dllEntry( systemcalls );
return libHandle;
}
/*
========================================================================
BACKGROUND FILE STREAMING
========================================================================
*/
//#define DO_STREAMING
typedef struct {
fileHandle_t file;
byte *buffer;
qboolean eof;
qboolean active;
int bufferSize;
int streamPosition; // next byte to be returned by Sys_StreamRead
int threadPosition; // next byte to be read from file
} streamsIO_t;
typedef struct {
HANDLE threadHandle;
int threadId;
HANDLE musicThreadHandle;
int musicThreadId;
CRITICAL_SECTION crit;
streamsIO_t sIO[64];
} streamState_t;
#ifdef DO_STREAMING
static streamState_t stream;
#endif
//int FS_ReadDirect( void *buffer, int len, fileHandle_t f );
int FS_Read2( void *buffer, int len, fileHandle_t f );
void Sys_MusicThread( void ) {
while ( 1 ) {
Sleep( 33 );
// S_Update_Debug();
S_AddLoopSounds();
S_UpdateThread();
}
}
#ifndef DO_STREAMING
void Sys_InitStreamThread( void ) {
}
void Sys_ShutdownStreamThread( void ) {
}
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 );
}
void *Sys_InitializeCriticalSection() {
return (void*)-1;
}
void Sys_EnterCriticalSection( void *ptr ) {
}
void Sys_LeaveCriticalSection( void *ptr ) {
}
#else
void Sys_StreamFillBuffer( int i ) {
int count;
int r;
int buffer;
int readCount;
int bufferPoint;
// if there is any space left in the buffer, fill it up
if ( stream.sIO[i].active && !stream.sIO[i].eof ) {
count = stream.sIO[i].bufferSize - ( stream.sIO[i].threadPosition - stream.sIO[i].streamPosition );
if ( !count ) {
return;
}
bufferPoint = stream.sIO[i].threadPosition % stream.sIO[i].bufferSize;
buffer = stream.sIO[i].bufferSize - bufferPoint;
readCount = buffer < count ? buffer : count;
//r = FS_ReadDirect( stream.sIO[i].buffer + bufferPoint, readCount, stream.sIO[i].file );
r = FS_Read2( stream.sIO[i].buffer + bufferPoint, readCount, stream.sIO[i].file );
if ( r != readCount ) {
stream.sIO[i].eof = qtrue;
}
stream.sIO[i].threadPosition += r;
}
}
/*
===============
Sys_StreamThread
A thread will be sitting in this loop forever
================
*/
void Sys_StreamThread( void ) {
int i;
while ( 1 ) {
Sleep( 10 );
EnterCriticalSection( &stream.crit );
for ( i = 1; i < 64; i++ ) {
Sys_StreamFillBuffer( i );
}
LeaveCriticalSection( &stream.crit );
}
}
/*
===============
Sys_InitStreamThread
================
*/
void Sys_InitStreamThread( void ) {
int i;
InitializeCriticalSection( &stream.crit );
stream.threadHandle = CreateThread(
NULL, // LPSECURITY_ATTRIBUTES lpsa,
0, // DWORD cbStack,
(LPTHREAD_START_ROUTINE)Sys_StreamThread, // LPTHREAD_START_ROUTINE lpStartAddr,
0, // LPVOID lpvThreadParm,
0, // DWORD fdwCreate,
&stream.threadId );
for ( i = 0; i < 64; i++ ) {
stream.sIO[i].active = qfalse;
}
stream.musicThreadHandle = CreateThread(
NULL, // LPSECURITY_ATTRIBUTES lpsa,
0, // DWORD cbStack,
(LPTHREAD_START_ROUTINE)Sys_MusicThread, // LPTHREAD_START_ROUTINE lpStartAddr,
0, // LPVOID lpvThreadParm,
0, // DWORD fdwCreate,
&stream.musicThreadId );
}
/*
===============
Sys_ShutdownStreamThread
================
*/
void Sys_ShutdownStreamThread( void ) {
}
/*
===============
Sys_BeginStreamedFile
================
*/
void Sys_BeginStreamedFile( fileHandle_t f, int readAhead ) {
if ( stream.sIO[f].file ) {
Sys_EndStreamedFile( stream.sIO[f].file );
}
stream.sIO[f].buffer = Z_Malloc( readAhead );
stream.sIO[f].bufferSize = readAhead;
stream.sIO[f].streamPosition = 0;
stream.sIO[f].threadPosition = 0;
stream.sIO[f].eof = qfalse;
stream.sIO[f].file = f;
stream.sIO[f].active = qtrue;
EnterCriticalSection( &stream.crit );
Sys_StreamFillBuffer( f );
LeaveCriticalSection( &stream.crit );
}
/*
===============
Sys_EndStreamedFile
================
*/
void Sys_EndStreamedFile( fileHandle_t f ) {
if ( f != stream.sIO[f].file ) {
Com_Error( ERR_FATAL, "Sys_EndStreamedFile: wrong file" );
}
EnterCriticalSection( &stream.crit );
stream.sIO[f].active = qfalse;
stream.sIO[f].file = 0;
Z_Free( stream.sIO[f].buffer );
stream.sIO[f].buffer = NULL;
LeaveCriticalSection( &stream.crit );
}
/*
===============
Sys_StreamedRead
================
*/
int Sys_StreamedRead( void *buffer, int size, int count, fileHandle_t f ) {
int available;
int remaining;
int sleepCount;
int copy;
int bufferCount;
int bufferPoint;
byte *dest;
if ( stream.sIO[f].active == qfalse ) {
Com_Error( ERR_FATAL, "Streamed read with non-streaming file" );
}
dest = (byte *)buffer;
remaining = size * count;
if ( remaining <= 0 ) {
Com_Error( ERR_FATAL, "Streamed read with non-positive size" );
}
sleepCount = 0;
while ( remaining > 0 ) {
available = stream.sIO[f].threadPosition - stream.sIO[f].streamPosition;
if ( !available ) {
if ( stream.sIO[f].eof ) {
break;
}
if ( sleepCount == 1 ) {
Com_DPrintf( "Sys_StreamedRead: waiting\n" );
}
if ( ++sleepCount > 100 ) {
Com_Error( ERR_FATAL, "Sys_StreamedRead: thread has died" );
}
Sleep( 10 );
continue;
}
bufferPoint = stream.sIO[f].streamPosition % stream.sIO[f].bufferSize;
bufferCount = stream.sIO[f].bufferSize - bufferPoint;
copy = available < bufferCount ? available : bufferCount;
if ( copy > remaining ) {
copy = remaining;
}
memcpy( dest, stream.sIO[f].buffer + bufferPoint, copy );
stream.sIO[f].streamPosition += copy;
dest += copy;
remaining -= copy;
}
return ( count * size - remaining ) / size;
}
/*
===============
Sys_StreamSeek
================
*/
void Sys_StreamSeek( fileHandle_t f, int offset, int origin ) {
// halt the thread
EnterCriticalSection( &stream.crit );
// clear to that point
FS_Seek( f, offset, origin );
stream.sIO[f].streamPosition = 0;
stream.sIO[f].threadPosition = 0;
stream.sIO[f].eof = qfalse;
// let the thread start running at the new position
LeaveCriticalSection( &stream.crit );
}
void *Sys_InitializeCriticalSection() {
LPCRITICAL_SECTION crit;
crit = malloc( sizeof( CRITICAL_SECTION ) );
InitializeCriticalSection( crit );
return crit;
}
void Sys_EnterCriticalSection( void *ptr ) {
LPCRITICAL_SECTION crit;
crit = ptr;
EnterCriticalSection( crit );
}
void Sys_LeaveCriticalSection( void *ptr ) {
LPCRITICAL_SECTION crit;
crit = ptr;
LeaveCriticalSection( crit );
}
#endif
/*
========================================================================
EVENT LOOP
========================================================================
*/
#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 ) {
Z_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_GetEvent
================
*/
sysEvent_t Sys_GetEvent( void ) {
MSG msg;
sysEvent_t ev;
char *s;
msg_t netmsg;
netadr_t adr;
// return if we have data
if ( eventHead > eventTail ) {
eventTail++;
return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ];
}
// pump the message loop
while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) {
if ( !GetMessage( &msg, NULL, 0, 0 ) ) {
Com_Quit_f();
}
// save the msg time, because wndprocs don't have access to the timestamp
g_wv.sysMsgTime = msg.time;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
// check for console commands
s = Sys_ConsoleInput();
if ( s ) {
char *b;
int len;
len = strlen( s ) + 1;
b = Z_Malloc( len );
Q_strncpyz( b, s, len - 1 );
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b );
}
// 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
// the readcount stepahead is for SOCKS support
len = sizeof( netadr_t ) + netmsg.cursize - netmsg.readcount;
buf = Z_Malloc( len );
*buf = adr;
memcpy( buf + 1, &netmsg.data[netmsg.readcount], netmsg.cursize - netmsg.readcount );
Sys_QueEvent( 0, SE_PACKET, 0, 0, len, buf );
}
// 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 = timeGetTime();
return ev;
}
//================================================================
/*
=================
Sys_In_Restart_f
Restart the input subsystem
=================
*/
void Sys_In_Restart_f( void ) {
IN_Shutdown();
IN_Init();
}
/*
=================
Sys_Net_Restart_f
Restart the network subsystem
=================
*/
void Sys_Net_Restart_f( void ) {
NET_Restart();
}
/*
================
Sys_Init
Called after the common systems (cvars, files, etc)
are initialized
================
*/
#define OSR2_BUILD_NUMBER 1111
#define WIN98_BUILD_NUMBER 1998
extern void Sys_ClearViewlog_f( void ); // fretn
void Sys_Init( void ) {
int cpuid;
// make sure the timer is high precision, otherwise
// NT gets 18ms resolution
timeBeginPeriod( 1 );
Cmd_AddCommand( "in_restart", Sys_In_Restart_f );
Cmd_AddCommand( "net_restart", Sys_Net_Restart_f );
Cmd_AddCommand( "clearviewlog", Sys_ClearViewlog_f );
g_wv.osversion.dwOSVersionInfoSize = sizeof( g_wv.osversion );
if ( !GetVersionEx( &g_wv.osversion ) ) {
Sys_Error( "Couldn't get OS info" );
}
if ( g_wv.osversion.dwMajorVersion < 4 ) {
Sys_Error( GAME_VERSION " requires Windows version 4 or greater" );
}
if ( g_wv.osversion.dwPlatformId == VER_PLATFORM_WIN32s ) {
Sys_Error( GAME_VERSION " doesn't run on Win32s" );
}
if ( g_wv.osversion.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
Cvar_Set( "arch", "winnt" );
} else if ( g_wv.osversion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) {
if ( LOWORD( g_wv.osversion.dwBuildNumber ) >= WIN98_BUILD_NUMBER ) {
Cvar_Set( "arch", "win98" );
} else if ( LOWORD( g_wv.osversion.dwBuildNumber ) >= OSR2_BUILD_NUMBER ) {
Cvar_Set( "arch", "win95 osr2.x" );
} else
{
Cvar_Set( "arch", "win95" );
}
} else
{
Cvar_Set( "arch", "unknown Windows variant" );
}
// save out a couple things in rom cvars for the renderer to access
Cvar_Get( "win_hinstance", va( "%i", (int)g_wv.hInstance ), CVAR_ROM );
Cvar_Get( "win_wndproc", va( "%i", (int)MainWndProc ), CVAR_ROM );
//
// figure out our CPU
//
Cvar_Get( "sys_cpustring", "detect", 0 );
if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "detect" ) ) {
Com_Printf( "...detecting CPU, found " );
cpuid = Sys_GetProcessorId();
switch ( cpuid )
{
case CPUID_GENERIC:
Cvar_Set( "sys_cpustring", "generic" );
break;
case CPUID_INTEL_UNSUPPORTED:
Cvar_Set( "sys_cpustring", "x86 (pre-Pentium)" );
break;
case CPUID_INTEL_PENTIUM:
Cvar_Set( "sys_cpustring", "x86 (P5/PPro, non-MMX)" );
break;
case CPUID_INTEL_MMX:
Cvar_Set( "sys_cpustring", "x86 (P5/Pentium2, MMX)" );
break;
case CPUID_INTEL_KATMAI:
Cvar_Set( "sys_cpustring", "Intel Pentium III" );
break;
case CPUID_AMD_3DNOW:
Cvar_Set( "sys_cpustring", "AMD w/ 3DNow!" );
break;
case CPUID_AXP:
Cvar_Set( "sys_cpustring", "Alpha AXP" );
break;
default:
Com_Error( ERR_FATAL, "Unknown cpu type %d\n", cpuid );
break;
}
} else
{
Com_Printf( "...forcing CPU type to " );
if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "generic" ) ) {
cpuid = CPUID_GENERIC;
} else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "x87" ) ) {
cpuid = CPUID_INTEL_PENTIUM;
} else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "mmx" ) ) {
cpuid = CPUID_INTEL_MMX;
} else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "3dnow" ) ) {
cpuid = CPUID_AMD_3DNOW;
} else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "PentiumIII" ) ) {
cpuid = CPUID_INTEL_KATMAI;
} else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "axp" ) ) {
cpuid = CPUID_AXP;
} else
{
Com_Printf( "WARNING: unknown sys_cpustring '%s'\n", Cvar_VariableString( "sys_cpustring" ) );
cpuid = CPUID_GENERIC;
}
}
Cvar_SetValue( "sys_cpuid", cpuid );
Com_Printf( "%s\n", Cvar_VariableString( "sys_cpustring" ) );
Cvar_Set( "username", Sys_GetCurrentUser() );
// IN_Init(); // FIXME: not in dedicated?
}
//=======================================================================
int totalMsec, countMsec;
/*
==================
WinMain
==================
*/
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {
char cwd[MAX_OSPATH];
int startTime, endTime;
// should never get a previous instance in Win32
if ( hPrevInstance ) {
return 0;
}
#ifdef EXCEPTION_HANDLER
WinSetExceptionVersion( Q3_VERSION );
#endif
g_wv.hInstance = hInstance;
Q_strncpyz( sys_cmdline, lpCmdLine, sizeof( sys_cmdline ) );
// done before Com/Sys_Init since we need this for error output
Sys_CreateConsole();
// no abort/retry/fail errors
SetErrorMode( SEM_FAILCRITICALERRORS );
// get the initial time base
Sys_Milliseconds();
#if 0
// if we find the CD, add a +set cddir xxx command line
Sys_ScanForCD();
#endif
Sys_InitStreamThread();
Com_Init( sys_cmdline );
NET_Init();
#ifndef DEDICATED
IN_Init(); // fretn - directinput must be inited after video etc
#endif
_getcwd( cwd, sizeof( cwd ) );
Com_Printf( "Working directory: %s\n", cwd );
// hide the early console since we've reached the point where we
// have a working graphics subsystems
if ( !com_dedicated->integer && !com_viewlog->integer ) {
Sys_ShowConsole( 0, qfalse );
}
SetFocus( g_wv.hWnd );
// main game loop
while ( 1 ) {
// if not running as a game client, sleep a bit
if ( g_wv.isMinimized || ( com_dedicated && com_dedicated->integer ) ) {
Sleep( 5 );
}
// set low precision every frame, because some system calls
// reset it arbitrarily
// _controlfp( _PC_24, _MCW_PC );
// _controlfp( -1, _MCW_EM ); // no exceptions, even if some crappy
// syscall turns them back on!
startTime = Sys_Milliseconds();
// make sure mouse and joystick are only called once a frame
IN_Frame();
// Com_FrameExt();
Com_Frame();
endTime = Sys_Milliseconds();
totalMsec += endTime - startTime;
countMsec++;
}
// never gets here
}
char *Sys_DefaultHomePath( void ) {
return NULL;
}
char *Sys_DefaultInstallPath( void ) {
return Sys_Cwd();
}
qboolean Sys_IsNumLockDown( void ) {
// thx juz ;)
SHORT state = GetKeyState( VK_NUMLOCK );
if ( state & 0x01 ) {
return qtrue;
}
return qfalse;
}
Jump to Line
Something went wrong with that request. Please try again.