|
|
1.1 root 1: // sys_win.h
2: #include "../qcommon/qcommon.h"
3: #include "winquake.h"
4: #include "resource.h"
5: #include <errno.h>
6: #include <float.h>
7: #include <fcntl.h>
8: #include <stdio.h>
9: #include <direct.h>
10: #include <io.h>
11: #include <conio.h>
12: #include "../win32/conproc.h"
13: #define MINIMUM_WIN_MEMORY 0x0a00000
14: #define MAXIMUM_WIN_MEMORY 0x1000000
15:
16: #define DEMO
17:
18: qboolean s_win95;
19: int starttime;
20: int ActiveApp;
21: qboolean Minimized;
22: static HANDLE hinput, houtput;
23:
24: unsigned sys_msg_time;
25: unsigned sys_frame_time;
26: static HANDLE qwclsemaphore;
27: #define MAX_NUM_ARGVS 128
28: int argc;
29: char *argv[MAX_NUM_ARGVS];
30:
31: /*
32: ===============================================================================
33: SYSTEM IO
34: ===============================================================================
35: */
36: void Sys_Error (char *error, ...)
37: {
38: va_list argptr;
39: char text[1024];
40: CL_Shutdown ();
41: Qcommon_Shutdown ();
42: va_start (argptr, error);
43: vsprintf (text, error, argptr);
44: va_end (argptr);
45: MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
46: if (qwclsemaphore)
47: CloseHandle (qwclsemaphore);
48: // shut down QHOST hooks if necessary
49: DeinitConProc ();
50:
51: exit (1);
52: }
53: void Sys_Quit (void)
54: {
55: timeEndPeriod( 1 );
56: CL_Shutdown();
57: Qcommon_Shutdown ();
58: CloseHandle (qwclsemaphore);
59: if (dedicated && dedicated->value)
60: FreeConsole ();
61: // shut down QHOST hooks if necessary
62: DeinitConProc ();
63:
64: exit (0);
65: }
66:
67:
68: void WinError (void)
69: {
70: LPVOID lpMsgBuf;
71:
72: FormatMessage(
73: FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
74: NULL,
75: GetLastError(),
76: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
77: (LPTSTR) &lpMsgBuf,
78: 0,
79: NULL
80: );
81:
82: // Display the string.
83: MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
84:
85: // Free the buffer.
86: LocalFree( lpMsgBuf );
87: }
88:
89: //================================================================
90:
91:
92: /*
93: ================
94: Sys_ScanForCD
95:
96: ================
97: */
98: char *Sys_ScanForCD (void)
99: {
100: static char cddir[MAX_OSPATH];
101: static qboolean done;
102: #ifndef DEMO
103: char drive[4];
104: FILE *f;
105: char test[MAX_QPATH];
106:
107: if (done) // don't re-check
108: return cddir;
109:
110: // no abort/retry/fail errors
111: SetErrorMode (SEM_FAILCRITICALERRORS);
112:
113: drive[0] = 'c';
114: drive[1] = ':';
115: drive[2] = '\\';
116: drive[3] = 0;
117:
118: done = true;
119:
120: // scan the drives
121: for (drive[0] = 'c' ; drive[0] <= 'z' ; drive[0]++)
122: {
123: // where activision put the stuff...
124: sprintf (cddir, "%sinstall\\data", drive);
125: sprintf (test, "%sinstall\\data\\quake2.exe", drive);
126: f = fopen(test, "r");
127: if (f)
128: {
129: fclose (f);
130: if (GetDriveType (drive) == DRIVE_CDROM)
131: return cddir;
132: }
133: }
134: #endif
135:
136: cddir[0] = 0;
137:
138: return NULL;
139: }
140:
141: /*
142: ================
143: Sys_CopyProtect
144:
145: ================
146: */
147: void Sys_CopyProtect (void)
148: {
149: #ifndef DEMO
150: char *cddir;
151:
152: cddir = Sys_ScanForCD();
153: if (!cddir[0])
154: Com_Error (ERR_FATAL, "You must have the Quake2 CD in the drive to play.");
155: #endif
156: }
157:
158: //================================================================
159:
160: /*
161: ================
162: Sys_Init
163: ================
164: */
165: void Sys_Init (void)
166: {
167: OSVERSIONINFO vinfo;
168: #if 0
169: // allocate a named semaphore on the client so the
170: // front end can tell if it is alive
171: // mutex will fail if semephore already exists
172: qwclsemaphore = CreateMutex(
173: NULL, /* Security attributes */
174: 0, /* owner */
175: "qwcl"); /* Semaphore name */
176: if (!qwclsemaphore)
177: Sys_Error ("QWCL is already running on this system");
178: CloseHandle (qwclsemaphore);
179: qwclsemaphore = CreateSemaphore(
180: NULL, /* Security attributes */
181: 0, /* Initial count */
182: 1, /* Maximum count */
183: "qwcl"); /* Semaphore name */
184: #endif
185:
186: timeBeginPeriod( 1 );
187: vinfo.dwOSVersionInfoSize = sizeof(vinfo);
188: if (!GetVersionEx (&vinfo))
189: Sys_Error ("Couldn't get OS info");
190: if (vinfo.dwMajorVersion < 4)
191: Sys_Error ("Quake2 requires windows version 4 or greater");
192: if (vinfo.dwPlatformId == VER_PLATFORM_WIN32s)
193: Sys_Error ("Quake2 doesn't run on Win32s");
194: else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
195: s_win95 = true;
196: if (dedicated->value)
197: {
198: if (!AllocConsole ())
199: Sys_Error ("Couldn't create dedicated server console");
200: hinput = GetStdHandle (STD_INPUT_HANDLE);
201: houtput = GetStdHandle (STD_OUTPUT_HANDLE);
202:
203: // let QHOST hook in
204: InitConProc (argc, argv);
205: }
206: }
207: static char console_text[256];
208: static int console_textlen;
209:
210: /*
211: ================
212: Sys_ConsoleInput
213: ================
214: */
215: char *Sys_ConsoleInput (void)
216: {
217: INPUT_RECORD recs[1024];
218: int dummy;
219: int ch, numread, numevents;
220: if (!dedicated || !dedicated->value)
221: return NULL;
222: for ( ;; )
223: {
224: if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
225: Sys_Error ("Error getting # of console events");
226: if (numevents <= 0)
227: break;
228: if (!ReadConsoleInput(hinput, recs, 1, &numread))
229: Sys_Error ("Error reading console input");
230: if (numread != 1)
231: Sys_Error ("Couldn't read console input");
232: if (recs[0].EventType == KEY_EVENT)
233: {
234: if (!recs[0].Event.KeyEvent.bKeyDown)
235: {
236: ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
237: switch (ch)
238: {
239: case '\r':
240: WriteFile(houtput, "\r\n", 2, &dummy, NULL);
241: if (console_textlen)
242: {
243: console_text[console_textlen] = 0;
244: console_textlen = 0;
245: return console_text;
246: }
247: break;
248: case '\b':
249: if (console_textlen)
250: {
251: console_textlen--;
252: WriteFile(houtput, "\b \b", 3, &dummy, NULL);
253: }
254: break;
255: default:
256: if (ch >= ' ')
257: {
258: if (console_textlen < sizeof(console_text)-2)
259: {
260: WriteFile(houtput, &ch, 1, &dummy, NULL);
261: console_text[console_textlen] = ch;
262: console_textlen++;
263: }
264: }
265: break;
266: }
267: }
268: }
269: }
270: return NULL;
271: }
272: /*
273: ================
274: Sys_ConsoleOutput
275: Print text to the dedicated console
276: ================
277: */
278: void Sys_ConsoleOutput (char *string)
279: {
280: int dummy;
281: char text[256];
282: if (!dedicated || !dedicated->value)
283: return;
284:
285: if (console_textlen)
286: {
287: text[0] = '\r';
288: memset(&text[1], ' ', console_textlen);
289: text[console_textlen+1] = '\r';
290: text[console_textlen+2] = 0;
291: WriteFile(houtput, text, console_textlen+2, &dummy, NULL);
292: }
293: WriteFile(houtput, string, strlen(string), &dummy, NULL);
294:
295: if (console_textlen)
296: WriteFile(houtput, console_text, console_textlen, &dummy, NULL);
297: }
298: /*
299: ================
300: Sys_SendKeyEvents
301: Send Key_Event calls
302: ================
303: */
304: void Sys_SendKeyEvents (void)
305: {
306: MSG msg;
307: while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
308: {
309: if (!GetMessage (&msg, NULL, 0, 0))
310: Sys_Quit ();
311: sys_msg_time = msg.time;
312: TranslateMessage (&msg);
313: DispatchMessage (&msg);
314: }
315:
316: // grab frame time
317: sys_frame_time = timeGetTime(); // FIXME: should this be at start?
318: }
319: /*
320: ================
321: Sys_GetClipboardData
322:
323: ================
324: */
325: char *Sys_GetClipboardData( void )
326: {
327: char *data = NULL;
328: char *cliptext;
329:
330: if ( OpenClipboard( NULL ) != 0 )
331: {
332: HANDLE hClipboardData;
333:
334: if ( ( hClipboardData = GetClipboardData( CF_TEXT ) ) != 0 )
335: {
336: if ( ( cliptext = GlobalLock( hClipboardData ) ) != 0 )
337: {
338: data = malloc( GlobalSize( hClipboardData ) + 1 );
339: strcpy( data, cliptext );
340: GlobalUnlock( hClipboardData );
341: }
342: }
343: CloseClipboard();
344: }
345: return data;
346: }
347: /*
348: ==============================================================================
349: WINDOWS CRAP
350: ==============================================================================
351: */
352: /*
353: =================
354: Sys_AppActivate
355: =================
356: */
357: void Sys_AppActivate (void)
358: {
359: ShowWindow ( cl_hwnd, SW_RESTORE);
360: SetForegroundWindow ( cl_hwnd );
361: }
362: /*
363: ========================================================================
364: GAME DLL
365: ========================================================================
366: */
367: static HINSTANCE game_library;
368: /*
369: =================
370: Sys_UnloadGame
371: =================
372: */
373: void Sys_UnloadGame (void)
374: {
375: if (!FreeLibrary (game_library))
376: Com_Error (ERR_FATAL, "FreeLibrary failed for game library");
377: game_library = NULL;
378: }
379: /*
380: =================
381: Sys_GetGameAPI
382: Loads the game dll
383: =================
384: */
385: void *Sys_GetGameAPI (void *parms)
386: {
387: void *(*GetGameAPI) (void *);
388: char name[MAX_OSPATH];
389: char *path;
390: char cwd[MAX_OSPATH];
391: #if defined _M_IX86
392: const char *gamename = "gamex86.dll";
393:
394: #ifdef NDEBUG
395: const char *debugdir = "release";
396: #else
397: const char *debugdir = "debug";
398: #endif
399:
400: #elif defined _M_ALPHA
401: const char *gamename = "gameaxp.dll";
402:
403: #ifdef NDEBUG
404: const char *debugdir = "releaseaxp";
405: #else
406: const char *debugdir = "debugaxp";
407: #endif
408:
409: #endif
410: if (game_library)
411: Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
412:
413: // check the current debug directory first for development purposes
414: _getcwd (cwd, sizeof(cwd));
415: Com_sprintf (name, sizeof(name), "%s/%s/%s", cwd, debugdir, gamename);
416: game_library = LoadLibrary ( name );
417: if (game_library)
418: {
419: Com_DPrintf ("LoadLibrary (%s)\n", name);
420: }
421: else
422: {
423: // check the current directory for other development purposes
424: Com_sprintf (name, sizeof(name), "%s/%s", cwd, gamename);
425: game_library = LoadLibrary ( name );
426: if (game_library)
427: {
428: Com_DPrintf ("LoadLibrary (%s)\n", name);
429: }
430: else
431: {
432: // now run through the search paths
433: path = NULL;
434: while (1)
435: {
436: path = FS_NextPath (path);
437: if (!path)
438: return NULL; // couldn't find one anywhere
439: Com_sprintf (name, sizeof(name), "%s/%s", path, gamename);
440: game_library = LoadLibrary (name);
441: if (game_library)
442: {
443: Com_DPrintf ("LoadLibrary (%s)\n",name);
444: break;
445: }
446: }
447: }
448: }
449: GetGameAPI = (void *)GetProcAddress (game_library, "GetGameAPI");
450: if (!GetGameAPI)
451: {
452: Sys_UnloadGame ();
453: return NULL;
454: }
455: return GetGameAPI (parms);
456: }
457: //=======================================================================
458: /*
459: ==================
460: ParseCommandLine
461: ==================
462: */
463: void ParseCommandLine (LPSTR lpCmdLine)
464: {
465: argc = 1;
466: argv[0] = "exe";
467: while (*lpCmdLine && (argc < MAX_NUM_ARGVS))
468: {
469: while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
470: lpCmdLine++;
471: if (*lpCmdLine)
472: {
473: argv[argc] = lpCmdLine;
474: argc++;
475: while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
476: lpCmdLine++;
477: if (*lpCmdLine)
478: {
479: *lpCmdLine = 0;
480: lpCmdLine++;
481: }
482:
483: }
484: }
485: }
486: /*
487: ==================
488: WinMain
489: ==================
490: */
491: HINSTANCE global_hInstance;
492: int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
493: {
494: MSG msg;
495: int time, oldtime, newtime;
496: char *cddir;
497:
498: /* previous instances do not exist in Win32 */
499: if (hPrevInstance)
500: return 0;
501:
502: global_hInstance = hInstance;
503: ParseCommandLine (lpCmdLine);
504: // if we find the CD, add a +set cddir xxx command line
505: cddir = Sys_ScanForCD ();
506: if (cddir && argc < MAX_NUM_ARGVS - 3)
507: {
508: int i;
509:
510: // don't override a cddir on the command line
511: for (i=0 ; i<argc ; i++)
512: if (!strcmp(argv[i], "cddir"))
513: break;
514: if (i == argc)
515: {
516: argv[argc++] = "+set";
517: argv[argc++] = "cddir";
518: argv[argc++] = cddir;
519: }
520: }
521: Qcommon_Init (argc, argv);
522: oldtime = Sys_Milliseconds ();
523: /* main window message loop */
524: while (1)
525: {
526: // if at a full screen console, don't update unless needed
527: if (Minimized || (dedicated && dedicated->value) )
528: {
529: Sleep (1);
530: }
531:
532: while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
533: {
534: if (!GetMessage (&msg, NULL, 0, 0))
535: Com_Quit ();
536: sys_msg_time = msg.time;
537: TranslateMessage (&msg);
538: DispatchMessage (&msg);
539: }
540: do
541: {
542: newtime = Sys_Milliseconds ();
543: time = newtime - oldtime;
544: } while (time < 1);
545: // Con_Printf ("time:%5.2f - %5.2f = %5.2f\n", newtime, oldtime, time);
546:
547: // _controlfp( ~( _EM_ZERODIVIDE /*| _EM_INVALID*/ ), _MCW_EM );
548: _controlfp( _PC_24, _MCW_PC );
549: Qcommon_Frame (time);
550: oldtime = newtime;
551: }
552: // never gets here
553: return TRUE;
554: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.