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