// sys_win.c -- Win32 system interface code /* * $Header: /H2 Mission Pack/SYS_WIN.C 8 4/13/98 1:01p Jmonroe $ */ #include "quakedef.h" #include #include "winquake.h" #include "errno.h" #include "resource.h" #define CRC_A 59461 // "Who's Ridin' With Chaos?" #define CRC_B 54866 // "Santa needs a new sled!" #ifdef GLQUAKE #define MINIMUM_WIN_MEMORY 0x1000000 #define MAXIMUM_WIN_MEMORY 0x1800000 #else #define MINIMUM_WIN_MEMORY 0x0C00000 #define MAXIMUM_WIN_MEMORY 0x1600000 #endif #define CONSOLE_ERROR_TIMEOUT 60.0 // # of seconds to wait on Sys_Error running // dedicated before exiting #define PAUSE_SLEEP 50 // sleep time on pause or minimization #define NOT_FOCUS_SLEEP 20 // sleep time when not focus int starttime; qboolean ActiveApp, Minimized; qboolean Win32AtLeastV4, WinNT; qboolean LegitCopy = true; static double pfreq; static double curtime = 0.0; static double lastcurtime = 0.0; static int lowshift; qboolean isDedicated; static qboolean sc_return_on_enter = false; HANDLE hinput, houtput; static char *tracking_tag = "Sticky Buns"; static HANDLE tevent; static HANDLE hFile; static HANDLE heventParent; static HANDLE heventChild; void MaskExceptions (void); void Sys_InitFloatTime (void); void Sys_PushFPCW_SetHigh (void); void Sys_PopFPCW (void); cvar_t sys_delay = {"sys_delay","0", true}; volatile int sys_checksum; /* ================ Sys_PageIn ================ */ void Sys_PageIn (void *ptr, int size) { byte *x; int j, m, n; // touch all the memory to make sure it's there. The 16-page skip is to // keep Win 95 from thinking we're trying to page ourselves in (we are // doing that, of course, but there's no reason we shouldn't) x = (byte *)ptr; for (n=0 ; n<4 ; n++) { for (m=0 ; m<(size - 16 * 0x1000) ; m += 4) { sys_checksum += *(int *)&x[m]; sys_checksum += *(int *)&x[m + 16 * 0x1000]; } } } /* =============================================================================== FILE IO =============================================================================== */ #define MAX_HANDLES 10 FILE *sys_handles[MAX_HANDLES]; int findhandle (void) { int i; for (i=1 ; i #define BuildTime 889138800 void CheckTime() { time_t now; int days; time( &now ); if ((now < BuildTime) || (now> BuildTime+26*24*60*60)) { errormessage = "This version has expired.@Please contact Activision for a new version"; LegitCopy = false; } } #endif /* ================ Sys_Init ================ */ void Sys_Init (void) { LARGE_INTEGER PerformanceFreq; unsigned int lowpart, highpart; OSVERSIONINFO vinfo; static char temp[MAX_PATH+1]; int value,i; HKEY hKey; DWORD dwSize,dwType; unsigned short crc; MaskExceptions (); Sys_SetFPCW (); if (!QueryPerformanceFrequency (&PerformanceFreq)) Sys_Error ("No hardware timer available"); // get 32 out of the 64 time bits such that we have around // 1 microsecond resolution lowpart = (unsigned int)PerformanceFreq.LowPart; highpart = (unsigned int)PerformanceFreq.HighPart; lowshift = 0; while (highpart || (lowpart > 2000000.0)) { lowshift++; lowpart >>= 1; lowpart |= (highpart & 1) << 31; highpart >>= 1; } pfreq = 1.0 / (double)lowpart; Sys_InitFloatTime (); vinfo.dwOSVersionInfoSize = sizeof(vinfo); if (!GetVersionEx (&vinfo)) Sys_Error ("Couldn't get OS info"); if (vinfo.dwMajorVersion < 4) Win32AtLeastV4 = false; else Win32AtLeastV4 = true; if (vinfo.dwPlatformId == VER_PLATFORM_WIN32s) Sys_Error ("Hexen2 requires at least Win95 or NT 4.0"); if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) WinNT = true; else WinNT = false; #ifdef SECURE dwSize = sizeof(temp); RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName", 0, KEY_READ, &hKey); value = RegQueryValueEx(hKey,"RAID2",NULL,&dwType,temp,&dwSize); if (value == ERROR_SUCCESS && dwType == REG_SZ) { CRC_Init(&crc); dwSize = strlen(temp); for(i=0;i> lowshift) | ((unsigned int)PerformanceCount.HighPart << (32 - lowshift)); if (first) { oldtime = temp; first = 0; } else { // check for turnover or backward time if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000)) { oldtime = temp; // so we can't get stuck } else { t2 = temp - oldtime; time = (double)t2 * pfreq; oldtime = temp; curtime += time; if (curtime == lastcurtime) { sametimecount++; if (sametimecount > 100000) { curtime += 1.0; sametimecount = 0; } } else { sametimecount = 0; } lastcurtime = curtime; } } Sys_PopFPCW (); return curtime; } /* ================ Sys_InitFloatTime ================ */ void Sys_InitFloatTime (void) { int j; Sys_FloatTime (); j = COM_CheckParm("-starttime"); if (j) { curtime = (double) (atof(com_argv[j+1])); } else { curtime = 0.0; } lastcurtime = curtime; } char *Sys_ConsoleInput (void) { static char text[256]; static int len; INPUT_RECORD recs[1024]; int count; int i, dummy; int ch, numread, numevents; if (!isDedicated) 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 (len) { text[len] = 0; len = 0; return text; } else if (sc_return_on_enter) { // special case to allow exiting from the error handler on Enter text[0] = '\r'; len = 0; return text; } break; case '\b': WriteFile(houtput, "\b \b", 3, &dummy, NULL); if (len) { len--; } break; default: if (ch >= ' ') { WriteFile(houtput, &ch, 1, &dummy, NULL); text[len] = ch; len = (len + 1) & 0xff; } break; } } } } return NULL; } void Sys_Sleep (void) { Sleep (1); } void Sys_SendKeyEvents (void) { MSG msg; while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) { // we always update if there are any event, even if we're paused scr_skipupdate = 0; if (!GetMessage (&msg, NULL, 0, 0)) Sys_Quit (); TranslateMessage (&msg); DispatchMessage (&msg); } } /* ============================================================================== WINDOWS CRAP ============================================================================== */ /* ================== WinMain ================== */ void SleepUntilInput (int time) { MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT); } /* ================== WinMain ================== */ HINSTANCE global_hInstance; int global_nCmdShow; char *argv[MAX_NUM_ARGVS]; static char *empty_string = ""; HWND hwnd_dialog; #ifdef GLQUAKE #define H2_PARAM_KEY "Software\\Hexen2" #define H2_FLAG_VALUE "Flag" #endif int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; quakeparms_t parms; double time, oldtime, newtime; MEMORYSTATUS lpBuffer; static char cwd[1024]; int t; #ifdef GLQUAKE HKEY hParamKey; BOOL FlagValue; DWORD cbBuffSize = sizeof(FlagValue); #endif /* previous instances do not exist in Win32 */ if (hPrevInstance) return 0; CL_RemoveGIPFiles(NULL); global_hInstance = hInstance; global_nCmdShow = nCmdShow; lpBuffer.dwLength = sizeof(MEMORYSTATUS); GlobalMemoryStatus (&lpBuffer); if (!GetCurrentDirectory (sizeof(cwd), cwd)) Sys_Error ("Couldn't determine current directory"); if (cwd[strlen(cwd)-1] == '/') cwd[strlen(cwd)-1] = 0; parms.basedir = cwd; parms.cachedir = NULL; parms.argc = 1; argv[0] = empty_string; while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS)) { while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126))) lpCmdLine++; if (*lpCmdLine) { argv[parms.argc] = lpCmdLine; parms.argc++; while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126))) lpCmdLine++; if (*lpCmdLine) { *lpCmdLine = 0; lpCmdLine++; } } } parms.argv = argv; COM_InitArgv (parms.argc, parms.argv); parms.argc = com_argc; parms.argv = com_argv; isDedicated = (COM_CheckParm ("-dedicated") != 0); if (!isDedicated) { #ifdef GLQUAKE RegCreateKeyEx(HKEY_LOCAL_MACHINE, H2_PARAM_KEY, 0, "GLH2", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hParamKey, NULL); if (RegQueryValueEx(hParamKey, H2_FLAG_VALUE, NULL, NULL, (LPBYTE)&FlagValue, &cbBuffSize) != ERROR_SUCCESS) { FlagValue = TRUE; RegSetValueEx(hParamKey, H2_FLAG_VALUE, 0, REG_BINARY, (LPBYTE)&FlagValue, sizeof(FlagValue)); MessageBox(NULL,"GLHexen is a special, accelerated version of Hexen II that runs on some OpenGL-based 3D cards. Note that not all 3D accelerator cards will work with GLHexen. If you are experiencing trouble launching GLHexen on your machine, your card is either not GLHexen compliant or you need to update your drivers. Consult your manufacturer for OpenGL compatibility and driver updates.","GLHexen2",MB_OK|MB_ICONSTOP); } #endif hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL); if (hwnd_dialog) { ShowWindow (hwnd_dialog, SW_SHOWDEFAULT); UpdateWindow (hwnd_dialog); SetForegroundWindow (hwnd_dialog); } } // take the greater of all the available memory or half the total memory, // but at least 8 Mb and no more than 16 Mb, unless they explicitly // request otherwise parms.memsize = lpBuffer.dwAvailPhys; if (parms.memsize < MINIMUM_WIN_MEMORY) parms.memsize = MINIMUM_WIN_MEMORY; if (parms.memsize < (lpBuffer.dwTotalPhys >> 1)) parms.memsize = lpBuffer.dwTotalPhys >> 1; if (parms.memsize > MAXIMUM_WIN_MEMORY) parms.memsize = MAXIMUM_WIN_MEMORY; if (COM_CheckParm ("-heapsize")) { t = COM_CheckParm("-heapsize") + 1; if (t < com_argc) parms.memsize = atoi (com_argv[t]) * 1024; } parms.membase = malloc (parms.memsize); if (!parms.membase) Sys_Error ("Not enough memory free; check disk space\n"); if(COM_CheckParm("-nopagein") == 0) { Sys_PageIn (parms.membase, parms.memsize); } tevent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!tevent) Sys_Error ("Couldn't create event"); if (isDedicated) { if (!AllocConsole ()) { Sys_Error ("Couldn't create dedicated server console"); } hinput = GetStdHandle (STD_INPUT_HANDLE); houtput = GetStdHandle (STD_OUTPUT_HANDLE); // give QHOST a chance to hook into the console if ((t = COM_CheckParm ("-HFILE")) > 0) { if (t < com_argc) hFile = (HANDLE)atoi (com_argv[t+1]); } if ((t = COM_CheckParm ("-HPARENT")) > 0) { if (t < com_argc) heventParent = (HANDLE)atoi (com_argv[t+1]); } if ((t = COM_CheckParm ("-HCHILD")) > 0) { if (t < com_argc) heventChild = (HANDLE)atoi (com_argv[t+1]); } InitConProc (hFile, heventParent, heventChild); } Sys_Init (); // because sound is off until we become active S_BlockSound (); Sys_Printf ("Host_Init\n"); Host_Init (&parms); oldtime = Sys_FloatTime (); Cvar_RegisterVariable (&sys_delay); /* main window message loop */ while (1) { if (isDedicated) { newtime = Sys_FloatTime (); time = newtime - oldtime; while (time < sys_ticrate.value ) { Sys_Sleep(); newtime = Sys_FloatTime (); time = newtime - oldtime; } } else { // yield the CPU for a little while when paused, minimized, or not the focus if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized) { SleepUntilInput (PAUSE_SLEEP); scr_skipupdate = 1; // no point in bothering to draw } else if (!ActiveApp && !DDActive) { SleepUntilInput (NOT_FOCUS_SLEEP); scr_skipupdate = 1; // no point in bothering to draw } newtime = Sys_FloatTime (); time = newtime - oldtime; } if (sys_delay.value) Sleep(sys_delay.value); Host_Frame (time); oldtime = newtime; } /* return success of application */ return TRUE; } /* * $Log: /H2 Mission Pack/SYS_WIN.C $ * * 8 4/13/98 1:01p Jmonroe * changed default to not use CDVolume * * 7 4/01/98 6:43p Jmonroe * fixed boundschecker errors * * 6 3/16/98 6:25p Jmonroe * set up euro secure checks * * 5 3/06/98 10:35a Jmonroe * * 4 3/05/98 5:13p Jmonroe * added pr build security shit * * 3 3/01/98 8:20p Jmonroe * removed the slow "quake" version of common functions * * 25 9/30/97 4:26p Rjohnson * Updates * * 24 9/23/97 8:56p Rjohnson * Updates * * 23 9/15/97 11:15a Rjohnson * Updates * * 22 9/04/97 4:44p Rjohnson * Updates * * 21 9/02/97 12:24a Rjohnson * Checks for a cd * * 20 8/31/97 3:44p Rjohnson * Memory change * * 19 8/27/97 12:10p Rjohnson * Increased max memory * * 18 8/21/97 10:12p Rjohnson * Demo Updates * * 17 8/21/97 11:05a Rjohnson * Deleting gip files * * 16 8/20/97 2:59p Rjohnson * Fix for crashes and saves * * 15 8/16/97 10:53a Rjohnson * Comment * * 14 8/01/97 4:30p Rjohnson * More encryption work * * 13 7/17/97 2:00p Rjohnson * Added a security means to control the running of the game * * 12 6/16/97 12:25p Rjohnson * Name changes from winquake to hexenii * * 11 6/16/97 3:13a Rjohnson * Fixes for: allocating less memory, models clipping out, and plaques in * gl version * * 10 5/13/97 4:54p Rjohnson * Increased the memory requirements for the gl version * * 9 5/01/97 12:18a Bgokey * * 8 3/21/97 11:05a Rjohnson * Increased minimum memory to 12 megs * * 7 3/07/97 2:24p Rjohnson * Id Updates * * 6 2/24/97 3:12p Bgokey * Added -nopagein. * * 5 2/18/97 4:55p Rjohnson * Id Updates * * 4 1/02/97 11:16a Rjohnson * Christmas work - added adaptive time, game delays, negative light, * particle effects, etc * * 3 12/10/96 12:22p Rjohnson * Code cleanup and made it so that quake won't try to do anything when it * isn't the active app */