123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- /*
- 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;
- }
|