home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / sys_win.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  17.1 KB  |  894 lines

  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.