Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 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. */
  20. // sys_win.c -- Win32 system interface code
  21.  
  22. #include "quakedef.h"
  23. #include "winquake.h"
  24. #include "errno.h"
  25. #include "resource.h"
  26. #include "conproc.h"
  27.  
  28. #define MINIMUM_WIN_MEMORY              0x0880000
  29. #define MAXIMUM_WIN_MEMORY              0x1000000
  30.  
  31. #define CONSOLE_ERROR_TIMEOUT   60.0    // # of seconds to wait on Sys_Error running
  32.                                                                                 //  dedicated before exiting
  33. #define PAUSE_SLEEP             50                              // sleep time on pause or minimization
  34. #define NOT_FOCUS_SLEEP 20                              // sleep time when not focus
  35.  
  36. int                     starttime;
  37. qboolean        ActiveApp, Minimized;
  38. qboolean        WinNT;
  39.  
  40. static double           pfreq;
  41. static double           curtime = 0.0;
  42. static double           lastcurtime = 0.0;
  43. static int                      lowshift;
  44. qboolean                        isDedicated;
  45. static qboolean         sc_return_on_enter = false;
  46. HANDLE                          hinput, houtput;
  47.  
  48. static char                     *tracking_tag = "Clams & Mooses";
  49.  
  50. static HANDLE   tevent;
  51. static HANDLE   hFile;
  52. static HANDLE   heventParent;
  53. static HANDLE   heventChild;
  54.  
  55. void MaskExceptions (void);
  56. void Sys_InitFloatTime (void);
  57. void Sys_PushFPCW_SetHigh (void);
  58. void Sys_PopFPCW (void);
  59.  
  60. volatile int                                    sys_checksum;
  61.  
  62.  
  63. /*
  64. ================
  65. Sys_PageIn
  66. ================
  67. */
  68. void Sys_PageIn (void *ptr, int size)
  69. {
  70.         byte    *x;
  71.         int             j, m, n;
  72.  
  73. // touch all the memory to make sure it's there. The 16-page skip is to
  74. // keep Win 95 from thinking we're trying to page ourselves in (we are
  75. // doing that, of course, but there's no reason we shouldn't)
  76.         x = (byte *)ptr;
  77.  
  78.         for (n=0 ; n<4 ; n++)
  79.         {
  80.                 for (m=0 ; m<(size - 16 * 0x1000) ; m += 4)
  81.                 {
  82.                         sys_checksum += *(int *)&x[m];
  83.                         sys_checksum += *(int *)&x[m + 16 * 0x1000];
  84.                 }
  85.         }
  86. }
  87.  
  88.  
  89. /*
  90. ===============================================================================
  91.  
  92. FILE IO
  93.  
  94. ===============================================================================
  95. */
  96.  
  97. #define MAX_HANDLES             10
  98. FILE    *sys_handles[MAX_HANDLES];
  99.  
  100. int             findhandle (void)
  101. {
  102.         int             i;
  103.        
  104.         for (i=1 ; i<MAX_HANDLES ; i++)
  105.                 if (!sys_handles[i])
  106.                         return i;
  107.         Sys_Error ("out of handles");
  108.         return -1;
  109. }
  110.  
  111. /*
  112. ================
  113. filelength
  114. ================
  115. */
  116. int filelength (FILE *f)
  117. {
  118.         int             pos;
  119.         int             end;
  120.         int             t;
  121.  
  122.         t = VID_ForceUnlockedAndReturnState ();
  123.  
  124.         pos = ftell (f);
  125.         fseek (f, 0, SEEK_END);
  126.         end = ftell (f);
  127.         fseek (f, pos, SEEK_SET);
  128.  
  129.         VID_ForceLockState (t);
  130.  
  131.         return end;
  132. }
  133.  
  134. int Sys_FileOpenRead (char *path, int *hndl)
  135. {
  136.         FILE    *f;
  137.         int             i, retval;
  138.         int             t;
  139.  
  140.         t = VID_ForceUnlockedAndReturnState ();
  141.  
  142.         i = findhandle ();
  143.  
  144.         f = fopen(path, "rb");
  145.  
  146.         if (!f)
  147.         {
  148.                 *hndl = -1;
  149.                 retval = -1;
  150.         }
  151.         else
  152.         {
  153.                 sys_handles[i] = f;
  154.                 *hndl = i;
  155.                 retval = filelength(f);
  156.         }
  157.  
  158.         VID_ForceLockState (t);
  159.  
  160.         return retval;
  161. }
  162.  
  163. int Sys_FileOpenWrite (char *path)
  164. {
  165.         FILE    *f;
  166.         int             i;
  167.         int             t;
  168.  
  169.         t = VID_ForceUnlockedAndReturnState ();
  170.        
  171.         i = findhandle ();
  172.  
  173.         f = fopen(path, "wb");
  174.         if (!f)
  175.                 Sys_Error ("Error opening %s: %s", path,strerror(errno));
  176.         sys_handles[i] = f;
  177.        
  178.         VID_ForceLockState (t);
  179.  
  180.         return i;
  181. }
  182.  
  183. void Sys_FileClose (int handle)
  184. {
  185.         int             t;
  186.  
  187.         t = VID_ForceUnlockedAndReturnState ();
  188.         fclose (sys_handles[handle]);
  189.         sys_handles[handle] = NULL;
  190.         VID_ForceLockState (t);
  191. }
  192.  
  193. void Sys_FileSeek (int handle, int position)
  194. {
  195.         int             t;
  196.  
  197.         t = VID_ForceUnlockedAndReturnState ();
  198.         fseek (sys_handles[handle], position, SEEK_SET);
  199.         VID_ForceLockState (t);
  200. }
  201.  
  202. int Sys_FileRead (int handle, void *dest, int count)
  203. {
  204.         int             t, x;
  205.  
  206.         t = VID_ForceUnlockedAndReturnState ();
  207.         x = fread (dest, 1, count, sys_handles[handle]);
  208.         VID_ForceLockState (t);
  209.         return x;
  210. }
  211.  
  212. int Sys_FileWrite (int handle, void *data, int count)
  213. {
  214.         int             t, x;
  215.  
  216.         t = VID_ForceUnlockedAndReturnState ();
  217.         x = fwrite (data, 1, count, sys_handles[handle]);
  218.         VID_ForceLockState (t);
  219.         return x;
  220. }
  221.  
  222. int     Sys_FileTime (char *path)
  223. {
  224.         FILE    *f;
  225.         int             t, retval;
  226.  
  227.         t = VID_ForceUnlockedAndReturnState ();
  228.        
  229.         f = fopen(path, "rb");
  230.  
  231.         if (f)
  232.         {
  233.                 fclose(f);
  234.                 retval = 1;
  235.         }
  236.         else
  237.         {
  238.                 retval = -1;
  239.         }
  240.        
  241.         VID_ForceLockState (t);
  242.         return retval;
  243. }
  244.  
  245. void Sys_mkdir (char *path)
  246. {
  247.         _mkdir (path);
  248. }
  249.  
  250.  
  251. /*
  252. ===============================================================================
  253.  
  254. SYSTEM IO
  255.  
  256. ===============================================================================
  257. */
  258.  
  259. /*
  260. ================
  261. Sys_MakeCodeWriteable
  262. ================
  263. */
  264. void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
  265. {
  266.         DWORD  flOldProtect;
  267.  
  268.         if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
  269.                 Sys_Error("Protection change failed\n");
  270. }
  271.  
  272.  
  273. #ifndef _M_IX86
  274.  
  275. void Sys_SetFPCW (void)
  276. {
  277. }
  278.  
  279. void Sys_PushFPCW_SetHigh (void)
  280. {
  281. }
  282.  
  283. void Sys_PopFPCW (void)
  284. {
  285. }
  286.  
  287. void MaskExceptions (void)
  288. {
  289. }
  290.  
  291. #endif
  292.  
  293. /*
  294. ================
  295. Sys_Init
  296. ================
  297. */
  298. void Sys_Init (void)
  299. {
  300.         LARGE_INTEGER   PerformanceFreq;
  301.         unsigned int    lowpart, highpart;
  302.         OSVERSIONINFO   vinfo;
  303.  
  304.         MaskExceptions ();
  305.         Sys_SetFPCW ();
  306.  
  307.         if (!QueryPerformanceFrequency (&PerformanceFreq))
  308.                 Sys_Error ("No hardware timer available");
  309.  
  310. // get 32 out of the 64 time bits such that we have around
  311. // 1 microsecond resolution
  312.         lowpart = (unsigned int)PerformanceFreq.LowPart;
  313.         highpart = (unsigned int)PerformanceFreq.HighPart;
  314.         lowshift = 0;
  315.  
  316.         while (highpart || (lowpart > 2000000.0))
  317.         {
  318.                 lowshift++;
  319.                 lowpart >>= 1;
  320.                 lowpart |= (highpart & 1) << 31;
  321.                 highpart >>= 1;
  322.         }
  323.  
  324.         pfreq = 1.0 / (double)lowpart;
  325.  
  326.         Sys_InitFloatTime ();
  327.  
  328.         vinfo.dwOSVersionInfoSize = sizeof(vinfo);
  329.  
  330.         if (!GetVersionEx (&vinfo))
  331.                 Sys_Error ("Couldn't get OS info");
  332.  
  333.         if ((vinfo.dwMajorVersion < 4) ||
  334.                 (vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
  335.         {
  336.                 Sys_Error ("WinQuake requires at least Win95 or NT 4.0");
  337.         }
  338.  
  339.         if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  340.                 WinNT = true;
  341.         else
  342.                 WinNT = false;
  343. }
  344.  
  345.  
  346. void Sys_Error (char *error, ...)
  347. {
  348.         va_list         argptr;
  349.         char            text[1024], text2[1024];
  350.         char            *text3 = "Press Enter to exit\n";
  351.         char            *text4 = "***********************************\n";
  352.         char            *text5 = "\n";
  353.         DWORD           dummy;
  354.         double          starttime;
  355.         static int      in_sys_error0 = 0;
  356.         static int      in_sys_error1 = 0;
  357.         static int      in_sys_error2 = 0;
  358.         static int      in_sys_error3 = 0;
  359.  
  360.         if (!in_sys_error3)
  361.         {
  362.                 in_sys_error3 = 1;
  363.                 VID_ForceUnlockedAndReturnState ();
  364.         }
  365.  
  366.         va_start (argptr, error);
  367.         vsprintf (text, error, argptr);
  368.         va_end (argptr);
  369.  
  370.         if (isDedicated)
  371.         {
  372.                 va_start (argptr, error);
  373.                 vsprintf (text, error, argptr);
  374.                 va_end (argptr);
  375.  
  376.                 sprintf (text2, "ERROR: %s\n", text);
  377.                 WriteFile (houtput, text5, strlen (text5), &dummy, NULL);
  378.                 WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
  379.                 WriteFile (houtput, text2, strlen (text2), &dummy, NULL);
  380.                 WriteFile (houtput, text3, strlen (text3), &dummy, NULL);
  381.                 WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
  382.  
  383.  
  384.                 starttime = Sys_FloatTime ();
  385.                 sc_return_on_enter = true;      // so Enter will get us out of here
  386.  
  387.                 while (!Sys_ConsoleInput () &&
  388.                                 ((Sys_FloatTime () - starttime) < CONSOLE_ERROR_TIMEOUT))
  389.                 {
  390.                 }
  391.         }
  392.         else
  393.         {
  394.         // switch to windowed so the message box is visible, unless we already
  395.         // tried that and failed
  396.                 if (!in_sys_error0)
  397.                 {
  398.                         in_sys_error0 = 1;
  399.                         VID_SetDefaultMode ();
  400.                         MessageBox(NULL, text, "Quake Error",
  401.                                            MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
  402.                 }
  403.                 else
  404.                 {
  405.                         MessageBox(NULL, text, "Double Quake Error",
  406.                                            MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
  407.                 }
  408.         }
  409.  
  410.         if (!in_sys_error1)
  411.         {
  412.                 in_sys_error1 = 1;
  413.                 Host_Shutdown ();
  414.         }
  415.  
  416. // shut down QHOST hooks if necessary
  417.         if (!in_sys_error2)
  418.         {
  419.                 in_sys_error2 = 1;
  420.                 DeinitConProc ();
  421.         }
  422.  
  423.         exit (1);
  424. }
  425.  
  426. void Sys_Printf (char *fmt, ...)
  427. {
  428.         va_list         argptr;
  429.         char            text[1024];
  430.         DWORD           dummy;
  431.        
  432.         if (isDedicated)
  433.         {
  434.                 va_start (argptr,fmt);
  435.                 vsprintf (text, fmt, argptr);
  436.                 va_end (argptr);
  437.  
  438.                 WriteFile(houtput, text, strlen (text), &dummy, NULL); 
  439.         }
  440. }
  441.  
  442. void Sys_Quit (void)
  443. {
  444.  
  445.         VID_ForceUnlockedAndReturnState ();
  446.  
  447.         Host_Shutdown();
  448.  
  449.         if (tevent)
  450.                 CloseHandle (tevent);
  451.  
  452.         if (isDedicated)
  453.                 FreeConsole ();
  454.  
  455. // shut down QHOST hooks if necessary
  456.         DeinitConProc ();
  457.  
  458.         exit (0);
  459. }
  460.  
  461.  
  462. /*
  463. ================
  464. Sys_FloatTime
  465. ================
  466. */
  467. double Sys_FloatTime (void)
  468. {
  469.         static int                      sametimecount;
  470.         static unsigned int     oldtime;
  471.         static int                      first = 1;
  472.         LARGE_INTEGER           PerformanceCount;
  473.         unsigned int            temp, t2;
  474.         double                          time;
  475.  
  476.         Sys_PushFPCW_SetHigh ();
  477.  
  478.         QueryPerformanceCounter (&PerformanceCount);
  479.  
  480.         temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
  481.                    ((unsigned int)PerformanceCount.HighPart << (32 - lowshift));
  482.  
  483.         if (first)
  484.         {
  485.                 oldtime = temp;
  486.                 first = 0;
  487.         }
  488.         else
  489.         {
  490.         // check for turnover or backward time
  491.                 if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
  492.                 {
  493.                         oldtime = temp; // so we can't get stuck
  494.                 }
  495.                 else
  496.                 {
  497.                         t2 = temp - oldtime;
  498.  
  499.                         time = (double)t2 * pfreq;
  500.                         oldtime = temp;
  501.  
  502.                         curtime += time;
  503.  
  504.                         if (curtime == lastcurtime)
  505.                         {
  506.                                 sametimecount++;
  507.  
  508.                                 if (sametimecount > 100000)
  509.                                 {
  510.                                         curtime += 1.0;
  511.                                         sametimecount = 0;
  512.                                 }
  513.                         }
  514.                         else
  515.                         {
  516.                                 sametimecount = 0;
  517.                         }
  518.  
  519.                         lastcurtime = curtime;
  520.                 }
  521.         }
  522.  
  523.         Sys_PopFPCW ();
  524.  
  525.     return curtime;
  526. }
  527.  
  528.  
  529. /*
  530. ================
  531. Sys_InitFloatTime
  532. ================
  533. */
  534. void Sys_InitFloatTime (void)
  535. {
  536.         int             j;
  537.  
  538.         Sys_FloatTime ();
  539.  
  540.         j = COM_CheckParm("-starttime");
  541.  
  542.         if (j)
  543.         {
  544.                 curtime = (double) (Q_atof(com_argv[j+1]));
  545.         }
  546.         else
  547.         {
  548.                 curtime = 0.0;
  549.         }
  550.  
  551.         lastcurtime = curtime;
  552. }
  553.  
  554.  
  555. char *Sys_ConsoleInput (void)
  556. {
  557.         static char     text[256];
  558.         static int              len;
  559.         INPUT_RECORD    recs[1024];
  560.         int             count;
  561.         int             i, dummy;
  562.         int             ch, numread, numevents;
  563.  
  564.         if (!isDedicated)
  565.                 return NULL;
  566.  
  567.  
  568.         for ( ;; )
  569.         {
  570.                 if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
  571.                         Sys_Error ("Error getting # of console events");
  572.  
  573.                 if (numevents <= 0)
  574.                         break;
  575.  
  576.                 if (!ReadConsoleInput(hinput, recs, 1, &numread))
  577.                         Sys_Error ("Error reading console input");
  578.  
  579.                 if (numread != 1)
  580.                         Sys_Error ("Couldn't read console input");
  581.  
  582.                 if (recs[0].EventType == KEY_EVENT)
  583.                 {
  584.                         if (!recs[0].Event.KeyEvent.bKeyDown)
  585.                         {
  586.                                 ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
  587.  
  588.                                 switch (ch)
  589.                                 {
  590.                                         case '\r':
  591.                                                 WriteFile(houtput, "\r\n", 2, &dummy, NULL);   
  592.  
  593.                                                 if (len)
  594.                                                 {
  595.                                                         text[len] = 0;
  596.                                                         len = 0;
  597.                                                         return text;
  598.                                                 }
  599.                                                 else if (sc_return_on_enter)
  600.                                                 {
  601.                                                 // special case to allow exiting from the error handler on Enter
  602.                                                         text[0] = '\r';
  603.                                                         len = 0;
  604.                                                         return text;
  605.                                                 }
  606.  
  607.                                                 break;
  608.  
  609.                                         case '\b':
  610.                                                 WriteFile(houtput, "\b \b", 3, &dummy, NULL);  
  611.                                                 if (len)
  612.                                                 {
  613.                                                         len--;
  614.                                                 }
  615.                                                 break;
  616.  
  617.                                         default:
  618.                                                 if (ch >= ' ')
  619.                                                 {
  620.                                                         WriteFile(houtput, &ch, 1, &dummy, NULL);      
  621.                                                         text[len] = ch;
  622.                                                         len = (len + 1) & 0xff;
  623.                                                 }
  624.  
  625.                                                 break;
  626.  
  627.                                 }
  628.                         }
  629.                 }
  630.         }
  631.  
  632.         return NULL;
  633. }
  634.  
  635. void Sys_Sleep (void)
  636. {
  637.         Sleep (1);
  638. }
  639.  
  640.  
  641. void Sys_SendKeyEvents (void)
  642. {
  643.     MSG        msg;
  644.  
  645.         while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
  646.         {
  647.         // we always update if there are any event, even if we're paused
  648.                 scr_skipupdate = 0;
  649.  
  650.                 if (!GetMessage (&msg, NULL, 0, 0))
  651.                         Sys_Quit ();
  652.  
  653.         TranslateMessage (&msg);
  654.         DispatchMessage (&msg);
  655.         }
  656. }
  657.  
  658.  
  659. /*
  660. ==============================================================================
  661.  
  662.  WINDOWS CRAP
  663.  
  664. ==============================================================================
  665. */
  666.  
  667.  
  668. /*
  669. ==================
  670. WinMain
  671. ==================
  672. */
  673. void SleepUntilInput (int time)
  674. {
  675.  
  676.         MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT);
  677. }
  678.  
  679.  
  680. /*
  681. ==================
  682. WinMain
  683. ==================
  684. */
  685. HINSTANCE       global_hInstance;
  686. int                     global_nCmdShow;
  687. char            *argv[MAX_NUM_ARGVS];
  688. static char     *empty_string = "";
  689. HWND            hwnd_dialog;
  690.  
  691.  
  692. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  693. {
  694.     MSG                         msg;
  695.         quakeparms_t    parms;
  696.         double                  time, oldtime, newtime;
  697.         MEMORYSTATUS    lpBuffer;
  698.         static  char    cwd[1024];
  699.         int                             t;
  700.         RECT                    rect;
  701.  
  702.     /* previous instances do not exist in Win32 */
  703.     if (hPrevInstance)
  704.         return 0;
  705.  
  706.         global_hInstance = hInstance;
  707.         global_nCmdShow = nCmdShow;
  708.  
  709.         lpBuffer.dwLength = sizeof(MEMORYSTATUS);
  710.         GlobalMemoryStatus (&lpBuffer);
  711.  
  712.         if (!GetCurrentDirectory (sizeof(cwd), cwd))
  713.                 Sys_Error ("Couldn't determine current directory");
  714.  
  715.         if (cwd[Q_strlen(cwd)-1] == '/')
  716.                 cwd[Q_strlen(cwd)-1] = 0;
  717.  
  718.         parms.basedir = cwd;
  719.         parms.cachedir = NULL;
  720.  
  721.         parms.argc = 1;
  722.         argv[0] = empty_string;
  723.  
  724.         while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
  725.         {
  726.                 while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
  727.                         lpCmdLine++;
  728.  
  729.                 if (*lpCmdLine)
  730.                 {
  731.                         argv[parms.argc] = lpCmdLine;
  732.                         parms.argc++;
  733.  
  734.                         while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
  735.                                 lpCmdLine++;
  736.  
  737.                         if (*lpCmdLine)
  738.                         {
  739.                                 *lpCmdLine = 0;
  740.                                 lpCmdLine++;
  741.                         }
  742.                        
  743.                 }
  744.         }
  745.  
  746.         parms.argv = argv;
  747.  
  748.         COM_InitArgv (parms.argc, parms.argv);
  749.  
  750.         parms.argc = com_argc;
  751.         parms.argv = com_argv;
  752.  
  753.         isDedicated = (COM_CheckParm ("-dedicated") != 0);
  754.  
  755.         if (!isDedicated)
  756.         {
  757.                 hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
  758.  
  759.                 if (hwnd_dialog)
  760.                 {
  761.                         if (GetWindowRect (hwnd_dialog, &rect))
  762.                         {
  763.                                 if (rect.left > (rect.top * 2))
  764.                                 {
  765.                                         SetWindowPos (hwnd_dialog, 0,
  766.                                                 (rect.left / 2) - ((rect.right - rect.left) / 2),
  767.                                                 rect.top, 0, 0,
  768.                                                 SWP_NOZORDER | SWP_NOSIZE);
  769.                                 }
  770.                         }
  771.  
  772.                         ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
  773.                         UpdateWindow (hwnd_dialog);
  774.                         SetForegroundWindow (hwnd_dialog);
  775.                 }
  776.         }
  777.  
  778. // take the greater of all the available memory or half the total memory,
  779. // but at least 8 Mb and no more than 16 Mb, unless they explicitly
  780. // request otherwise
  781.         parms.memsize = lpBuffer.dwAvailPhys;
  782.  
  783.         if (parms.memsize < MINIMUM_WIN_MEMORY)
  784.                 parms.memsize = MINIMUM_WIN_MEMORY;
  785.  
  786.         if (parms.memsize < (lpBuffer.dwTotalPhys >> 1))
  787.                 parms.memsize = lpBuffer.dwTotalPhys >> 1;
  788.  
  789.         if (parms.memsize > MAXIMUM_WIN_MEMORY)
  790.                 parms.memsize = MAXIMUM_WIN_MEMORY;
  791.  
  792.         if (COM_CheckParm ("-heapsize"))
  793.         {
  794.                 t = COM_CheckParm("-heapsize") + 1;
  795.  
  796.                 if (t < com_argc)
  797.                         parms.memsize = Q_atoi (com_argv[t]) * 1024;
  798.         }
  799.  
  800.         parms.membase = malloc (parms.memsize);
  801.  
  802.         if (!parms.membase)
  803.                 Sys_Error ("Not enough memory free; check disk space\n");
  804.  
  805.         Sys_PageIn (parms.membase, parms.memsize);
  806.  
  807.         tevent = CreateEvent(NULL, FALSE, FALSE, NULL);
  808.  
  809.         if (!tevent)
  810.                 Sys_Error ("Couldn't create event");
  811.  
  812.         if (isDedicated)
  813.         {
  814.                 if (!AllocConsole ())
  815.                 {
  816.                         Sys_Error ("Couldn't create dedicated server console");
  817.                 }
  818.  
  819.                 hinput = GetStdHandle (STD_INPUT_HANDLE);
  820.                 houtput = GetStdHandle (STD_OUTPUT_HANDLE);
  821.  
  822.         // give QHOST a chance to hook into the console
  823.                 if ((t = COM_CheckParm ("-HFILE")) > 0)
  824.                 {
  825.                         if (t < com_argc)
  826.                                 hFile = (HANDLE)Q_atoi (com_argv[t+1]);
  827.                 }
  828.                        
  829.                 if ((t = COM_CheckParm ("-HPARENT")) > 0)
  830.                 {
  831.                         if (t < com_argc)
  832.                                 heventParent = (HANDLE)Q_atoi (com_argv[t+1]);
  833.                 }
  834.                        
  835.                 if ((t = COM_CheckParm ("-HCHILD")) > 0)
  836.                 {
  837.                         if (t < com_argc)
  838.                                 heventChild = (HANDLE)Q_atoi (com_argv[t+1]);
  839.                 }
  840.  
  841.                 InitConProc (hFile, heventParent, heventChild);
  842.         }
  843.  
  844.         Sys_Init ();
  845.  
  846. // because sound is off until we become active
  847.         S_BlockSound ();
  848.  
  849.         Sys_Printf ("Host_Init\n");
  850.         Host_Init (&parms);
  851.  
  852.         oldtime = Sys_FloatTime ();
  853.  
  854.     /* main window message loop */
  855.         while (1)
  856.         {
  857.                 if (isDedicated)
  858.                 {
  859.                         newtime = Sys_FloatTime ();
  860.                         time = newtime - oldtime;
  861.  
  862.                         while (time < sys_ticrate.value )
  863.                         {
  864.                                 Sys_Sleep();
  865.                                 newtime = Sys_FloatTime ();
  866.                                 time = newtime - oldtime;
  867.                         }
  868.                 }
  869.                 else
  870.                 {
  871.                 // yield the CPU for a little while when paused, minimized, or not the focus
  872.                         if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing)
  873.                         {
  874.                                 SleepUntilInput (PAUSE_SLEEP);
  875.                                 scr_skipupdate = 1;             // no point in bothering to draw
  876.                         }
  877.                         else if (!ActiveApp && !DDActive)
  878.                         {
  879.                                 SleepUntilInput (NOT_FOCUS_SLEEP);
  880.                         }
  881.  
  882.                         newtime = Sys_FloatTime ();
  883.                         time = newtime - oldtime;
  884.                 }
  885.  
  886.                 Host_Frame (time);
  887.                 oldtime = newtime;
  888.         }
  889.  
  890.     /* return success of application */
  891.     return TRUE;
  892. }
  893.  
  894.