mirror of
https://github.com/id-Software/Quake-2.git
synced 2026-03-20 08:59:51 +01:00
The original Quake 2 sources as originally released under the GPL license on December 21, 2001.
This commit is contained in:
663
win32/sys_win.c
Normal file
663
win32/sys_win.c
Normal file
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program 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 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// sys_win.h
|
||||
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "winquake.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>
|
||||
#include "../win32/conproc.h"
|
||||
|
||||
#define MINIMUM_WIN_MEMORY 0x0a00000
|
||||
#define MAXIMUM_WIN_MEMORY 0x1000000
|
||||
|
||||
//#define DEMO
|
||||
|
||||
qboolean s_win95;
|
||||
|
||||
int starttime;
|
||||
int ActiveApp;
|
||||
qboolean Minimized;
|
||||
|
||||
static HANDLE hinput, houtput;
|
||||
|
||||
unsigned sys_msg_time;
|
||||
unsigned sys_frame_time;
|
||||
|
||||
|
||||
static HANDLE qwclsemaphore;
|
||||
|
||||
#define MAX_NUM_ARGVS 128
|
||||
int argc;
|
||||
char *argv[MAX_NUM_ARGVS];
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
SYSTEM IO
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
void Sys_Error (char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char text[1024];
|
||||
|
||||
CL_Shutdown ();
|
||||
Qcommon_Shutdown ();
|
||||
|
||||
va_start (argptr, error);
|
||||
vsprintf (text, error, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
|
||||
|
||||
if (qwclsemaphore)
|
||||
CloseHandle (qwclsemaphore);
|
||||
|
||||
// shut down QHOST hooks if necessary
|
||||
DeinitConProc ();
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void Sys_Quit (void)
|
||||
{
|
||||
timeEndPeriod( 1 );
|
||||
|
||||
CL_Shutdown();
|
||||
Qcommon_Shutdown ();
|
||||
CloseHandle (qwclsemaphore);
|
||||
if (dedicated && dedicated->value)
|
||||
FreeConsole ();
|
||||
|
||||
// shut down QHOST hooks if necessary
|
||||
DeinitConProc ();
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
void WinError (void)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
// Display the string.
|
||||
MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
|
||||
|
||||
// Free the buffer.
|
||||
LocalFree( lpMsgBuf );
|
||||
}
|
||||
|
||||
//================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_ScanForCD
|
||||
|
||||
================
|
||||
*/
|
||||
char *Sys_ScanForCD (void)
|
||||
{
|
||||
static char cddir[MAX_OSPATH];
|
||||
static qboolean done;
|
||||
#ifndef DEMO
|
||||
char drive[4];
|
||||
FILE *f;
|
||||
char test[MAX_QPATH];
|
||||
|
||||
if (done) // don't re-check
|
||||
return cddir;
|
||||
|
||||
// no abort/retry/fail errors
|
||||
SetErrorMode (SEM_FAILCRITICALERRORS);
|
||||
|
||||
drive[0] = 'c';
|
||||
drive[1] = ':';
|
||||
drive[2] = '\\';
|
||||
drive[3] = 0;
|
||||
|
||||
done = true;
|
||||
|
||||
// scan the drives
|
||||
for (drive[0] = 'c' ; drive[0] <= 'z' ; drive[0]++)
|
||||
{
|
||||
// where activision put the stuff...
|
||||
sprintf (cddir, "%sinstall\\data", drive);
|
||||
sprintf (test, "%sinstall\\data\\quake2.exe", drive);
|
||||
f = fopen(test, "r");
|
||||
if (f)
|
||||
{
|
||||
fclose (f);
|
||||
if (GetDriveType (drive) == DRIVE_CDROM)
|
||||
return cddir;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cddir[0] = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_CopyProtect
|
||||
|
||||
================
|
||||
*/
|
||||
void Sys_CopyProtect (void)
|
||||
{
|
||||
#ifndef DEMO
|
||||
char *cddir;
|
||||
|
||||
cddir = Sys_ScanForCD();
|
||||
if (!cddir[0])
|
||||
Com_Error (ERR_FATAL, "You must have the Quake2 CD in the drive to play.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Init
|
||||
================
|
||||
*/
|
||||
void Sys_Init (void)
|
||||
{
|
||||
OSVERSIONINFO vinfo;
|
||||
|
||||
#if 0
|
||||
// allocate a named semaphore on the client so the
|
||||
// front end can tell if it is alive
|
||||
|
||||
// mutex will fail if semephore already exists
|
||||
qwclsemaphore = CreateMutex(
|
||||
NULL, /* Security attributes */
|
||||
0, /* owner */
|
||||
"qwcl"); /* Semaphore name */
|
||||
if (!qwclsemaphore)
|
||||
Sys_Error ("QWCL is already running on this system");
|
||||
CloseHandle (qwclsemaphore);
|
||||
|
||||
qwclsemaphore = CreateSemaphore(
|
||||
NULL, /* Security attributes */
|
||||
0, /* Initial count */
|
||||
1, /* Maximum count */
|
||||
"qwcl"); /* Semaphore name */
|
||||
#endif
|
||||
|
||||
timeBeginPeriod( 1 );
|
||||
|
||||
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
|
||||
|
||||
if (!GetVersionEx (&vinfo))
|
||||
Sys_Error ("Couldn't get OS info");
|
||||
|
||||
if (vinfo.dwMajorVersion < 4)
|
||||
Sys_Error ("Quake2 requires windows version 4 or greater");
|
||||
if (vinfo.dwPlatformId == VER_PLATFORM_WIN32s)
|
||||
Sys_Error ("Quake2 doesn't run on Win32s");
|
||||
else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
||||
s_win95 = true;
|
||||
|
||||
if (dedicated->value)
|
||||
{
|
||||
if (!AllocConsole ())
|
||||
Sys_Error ("Couldn't create dedicated server console");
|
||||
hinput = GetStdHandle (STD_INPUT_HANDLE);
|
||||
houtput = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
|
||||
// let QHOST hook in
|
||||
InitConProc (argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char console_text[256];
|
||||
static int console_textlen;
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_ConsoleInput
|
||||
================
|
||||
*/
|
||||
char *Sys_ConsoleInput (void)
|
||||
{
|
||||
INPUT_RECORD recs[1024];
|
||||
int dummy;
|
||||
int ch, numread, numevents;
|
||||
|
||||
if (!dedicated || !dedicated->value)
|
||||
return NULL;
|
||||
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
|
||||
Sys_Error ("Error getting # of console events");
|
||||
|
||||
if (numevents <= 0)
|
||||
break;
|
||||
|
||||
if (!ReadConsoleInput(hinput, recs, 1, &numread))
|
||||
Sys_Error ("Error reading console input");
|
||||
|
||||
if (numread != 1)
|
||||
Sys_Error ("Couldn't read console input");
|
||||
|
||||
if (recs[0].EventType == KEY_EVENT)
|
||||
{
|
||||
if (!recs[0].Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '\r':
|
||||
WriteFile(houtput, "\r\n", 2, &dummy, NULL);
|
||||
|
||||
if (console_textlen)
|
||||
{
|
||||
console_text[console_textlen] = 0;
|
||||
console_textlen = 0;
|
||||
return console_text;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
if (console_textlen)
|
||||
{
|
||||
console_textlen--;
|
||||
WriteFile(houtput, "\b \b", 3, &dummy, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ch >= ' ')
|
||||
{
|
||||
if (console_textlen < sizeof(console_text)-2)
|
||||
{
|
||||
WriteFile(houtput, &ch, 1, &dummy, NULL);
|
||||
console_text[console_textlen] = ch;
|
||||
console_textlen++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_ConsoleOutput
|
||||
|
||||
Print text to the dedicated console
|
||||
================
|
||||
*/
|
||||
void Sys_ConsoleOutput (char *string)
|
||||
{
|
||||
int dummy;
|
||||
char text[256];
|
||||
|
||||
if (!dedicated || !dedicated->value)
|
||||
return;
|
||||
|
||||
if (console_textlen)
|
||||
{
|
||||
text[0] = '\r';
|
||||
memset(&text[1], ' ', console_textlen);
|
||||
text[console_textlen+1] = '\r';
|
||||
text[console_textlen+2] = 0;
|
||||
WriteFile(houtput, text, console_textlen+2, &dummy, NULL);
|
||||
}
|
||||
|
||||
WriteFile(houtput, string, strlen(string), &dummy, NULL);
|
||||
|
||||
if (console_textlen)
|
||||
WriteFile(houtput, console_text, console_textlen, &dummy, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_SendKeyEvents
|
||||
|
||||
Send Key_Event calls
|
||||
================
|
||||
*/
|
||||
void Sys_SendKeyEvents (void)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||
{
|
||||
if (!GetMessage (&msg, NULL, 0, 0))
|
||||
Sys_Quit ();
|
||||
sys_msg_time = msg.time;
|
||||
TranslateMessage (&msg);
|
||||
DispatchMessage (&msg);
|
||||
}
|
||||
|
||||
// grab frame time
|
||||
sys_frame_time = timeGetTime(); // FIXME: should this be at start?
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
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 = malloc( GlobalSize( hClipboardData ) + 1 );
|
||||
strcpy( data, cliptext );
|
||||
GlobalUnlock( hClipboardData );
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
WINDOWS CRAP
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_AppActivate
|
||||
=================
|
||||
*/
|
||||
void Sys_AppActivate (void)
|
||||
{
|
||||
ShowWindow ( cl_hwnd, SW_RESTORE);
|
||||
SetForegroundWindow ( cl_hwnd );
|
||||
}
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
GAME DLL
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
static HINSTANCE game_library;
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_UnloadGame
|
||||
=================
|
||||
*/
|
||||
void Sys_UnloadGame (void)
|
||||
{
|
||||
if (!FreeLibrary (game_library))
|
||||
Com_Error (ERR_FATAL, "FreeLibrary failed for game library");
|
||||
game_library = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_GetGameAPI
|
||||
|
||||
Loads the game dll
|
||||
=================
|
||||
*/
|
||||
void *Sys_GetGameAPI (void *parms)
|
||||
{
|
||||
void *(*GetGameAPI) (void *);
|
||||
char name[MAX_OSPATH];
|
||||
char *path;
|
||||
char cwd[MAX_OSPATH];
|
||||
#if defined _M_IX86
|
||||
const char *gamename = "gamex86.dll";
|
||||
|
||||
#ifdef NDEBUG
|
||||
const char *debugdir = "release";
|
||||
#else
|
||||
const char *debugdir = "debug";
|
||||
#endif
|
||||
|
||||
#elif defined _M_ALPHA
|
||||
const char *gamename = "gameaxp.dll";
|
||||
|
||||
#ifdef NDEBUG
|
||||
const char *debugdir = "releaseaxp";
|
||||
#else
|
||||
const char *debugdir = "debugaxp";
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
if (game_library)
|
||||
Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
|
||||
|
||||
// check the current debug directory first for development purposes
|
||||
_getcwd (cwd, sizeof(cwd));
|
||||
Com_sprintf (name, sizeof(name), "%s/%s/%s", cwd, debugdir, gamename);
|
||||
game_library = LoadLibrary ( name );
|
||||
if (game_library)
|
||||
{
|
||||
Com_DPrintf ("LoadLibrary (%s)\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check the current directory for other development purposes
|
||||
Com_sprintf (name, sizeof(name), "%s/%s", cwd, gamename);
|
||||
game_library = LoadLibrary ( name );
|
||||
if (game_library)
|
||||
{
|
||||
Com_DPrintf ("LoadLibrary (%s)\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// now run through the search paths
|
||||
path = NULL;
|
||||
while (1)
|
||||
{
|
||||
path = FS_NextPath (path);
|
||||
if (!path)
|
||||
return NULL; // couldn't find one anywhere
|
||||
Com_sprintf (name, sizeof(name), "%s/%s", path, gamename);
|
||||
game_library = LoadLibrary (name);
|
||||
if (game_library)
|
||||
{
|
||||
Com_DPrintf ("LoadLibrary (%s)\n",name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetGameAPI = (void *)GetProcAddress (game_library, "GetGameAPI");
|
||||
if (!GetGameAPI)
|
||||
{
|
||||
Sys_UnloadGame ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GetGameAPI (parms);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
ParseCommandLine
|
||||
|
||||
==================
|
||||
*/
|
||||
void ParseCommandLine (LPSTR lpCmdLine)
|
||||
{
|
||||
argc = 1;
|
||||
argv[0] = "exe";
|
||||
|
||||
while (*lpCmdLine && (argc < MAX_NUM_ARGVS))
|
||||
{
|
||||
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
|
||||
lpCmdLine++;
|
||||
|
||||
if (*lpCmdLine)
|
||||
{
|
||||
argv[argc] = lpCmdLine;
|
||||
argc++;
|
||||
|
||||
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
|
||||
lpCmdLine++;
|
||||
|
||||
if (*lpCmdLine)
|
||||
{
|
||||
*lpCmdLine = 0;
|
||||
lpCmdLine++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
WinMain
|
||||
|
||||
==================
|
||||
*/
|
||||
HINSTANCE global_hInstance;
|
||||
|
||||
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
MSG msg;
|
||||
int time, oldtime, newtime;
|
||||
char *cddir;
|
||||
|
||||
/* previous instances do not exist in Win32 */
|
||||
if (hPrevInstance)
|
||||
return 0;
|
||||
|
||||
global_hInstance = hInstance;
|
||||
|
||||
ParseCommandLine (lpCmdLine);
|
||||
|
||||
// if we find the CD, add a +set cddir xxx command line
|
||||
cddir = Sys_ScanForCD ();
|
||||
if (cddir && argc < MAX_NUM_ARGVS - 3)
|
||||
{
|
||||
int i;
|
||||
|
||||
// don't override a cddir on the command line
|
||||
for (i=0 ; i<argc ; i++)
|
||||
if (!strcmp(argv[i], "cddir"))
|
||||
break;
|
||||
if (i == argc)
|
||||
{
|
||||
argv[argc++] = "+set";
|
||||
argv[argc++] = "cddir";
|
||||
argv[argc++] = cddir;
|
||||
}
|
||||
}
|
||||
|
||||
Qcommon_Init (argc, argv);
|
||||
oldtime = Sys_Milliseconds ();
|
||||
|
||||
/* main window message loop */
|
||||
while (1)
|
||||
{
|
||||
// if at a full screen console, don't update unless needed
|
||||
if (Minimized || (dedicated && dedicated->value) )
|
||||
{
|
||||
Sleep (1);
|
||||
}
|
||||
|
||||
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||
{
|
||||
if (!GetMessage (&msg, NULL, 0, 0))
|
||||
Com_Quit ();
|
||||
sys_msg_time = msg.time;
|
||||
TranslateMessage (&msg);
|
||||
DispatchMessage (&msg);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
newtime = Sys_Milliseconds ();
|
||||
time = newtime - oldtime;
|
||||
} while (time < 1);
|
||||
// Con_Printf ("time:%5.2f - %5.2f = %5.2f\n", newtime, oldtime, time);
|
||||
|
||||
// _controlfp( ~( _EM_ZERODIVIDE /*| _EM_INVALID*/ ), _MCW_EM );
|
||||
_controlfp( _PC_24, _MCW_PC );
|
||||
Qcommon_Frame (time);
|
||||
|
||||
oldtime = newtime;
|
||||
}
|
||||
|
||||
// never gets here
|
||||
return TRUE;
|
||||
}
|
||||
Reference in New Issue
Block a user