home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / sys_win.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  14.2 KB  |  699 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.h
  21.  
  22. #include "quakedef.h"
  23. #include "winquake.h"
  24. #include "resource.h"
  25. #include "errno.h"
  26. #include "fcntl.h"
  27. #include <limits.h>
  28.  
  29. #define MINIMUM_WIN_MEMORY  0x0c00000
  30. #define MAXIMUM_WIN_MEMORY  0x1000000
  31.  
  32. #define PAUSE_SLEEP   50        // sleep time on pause or minimization
  33. #define NOT_FOCUS_SLEEP 20        // sleep time when not focus
  34.  
  35. int   starttime;
  36. qboolean ActiveApp, Minimized;
  37. qboolean  WinNT;
  38.  
  39. HWND  hwnd_dialog;    // startup dialog box
  40.  
  41. static double   pfreq;
  42. static double   curtime = 0.0;
  43. static double   lastcurtime = 0.0;
  44. static int      lowshift;
  45. static HANDLE   hinput, houtput;
  46.  
  47. HANDLE    qwclsemaphore;
  48.  
  49. static HANDLE tevent;
  50.  
  51. void Sys_InitFloatTime (void);
  52.  
  53. void MaskExceptions (void);
  54. void Sys_PopFPCW (void);
  55. void Sys_PushFPCW_SetHigh (void);
  56.  
  57. void Sys_DebugLog(char *file, char *fmt, ...)
  58. {
  59.     va_list argptr; 
  60.     static char data[1024];
  61.     int fd;
  62.     
  63.     va_start(argptr, fmt);
  64.     vsprintf(data, fmt, argptr);
  65.     va_end(argptr);
  66.     fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
  67.     write(fd, data, strlen(data));
  68.     close(fd);
  69. };
  70.  
  71. /*
  72. ===============================================================================
  73.  
  74. FILE IO
  75.  
  76. ===============================================================================
  77. */
  78.  
  79. /*
  80. ================
  81. filelength
  82. ================
  83. */
  84. int filelength (FILE *f)
  85. {
  86.   int   pos;
  87.   int   end;
  88.  
  89.   pos = ftell (f);
  90.   fseek (f, 0, SEEK_END);
  91.   end = ftell (f);
  92.   fseek (f, pos, SEEK_SET);
  93.  
  94.   return end;
  95. }
  96.  
  97.  
  98. int Sys_FileTime (char *path)
  99. {
  100.   FILE  *f;
  101.   int   t, retval;
  102.  
  103.   t = VID_ForceUnlockedAndReturnState ();
  104.   
  105.   f = fopen(path, "rb");
  106.  
  107.   if (f)
  108.   {
  109.     fclose(f);
  110.     retval = 1;
  111.   }
  112.   else
  113.   {
  114.     retval = -1;
  115.   }
  116.   
  117.   VID_ForceLockState (t);
  118.   return retval;
  119. }
  120.  
  121. void Sys_mkdir (char *path)
  122. {
  123.   _mkdir (path);
  124. }
  125.  
  126.  
  127. /*
  128. ===============================================================================
  129.  
  130. SYSTEM IO
  131.  
  132. ===============================================================================
  133. */
  134.  
  135. /*
  136. ================
  137. Sys_MakeCodeWriteable
  138. ================
  139. */
  140. void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
  141. {
  142.   DWORD  flOldProtect;
  143.  
  144. //@@@ copy on write or just read-write?
  145.   if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
  146.       Sys_Error("Protection change failed\n");
  147. }
  148.  
  149.  
  150. /*
  151. ================
  152. Sys_Init
  153. ================
  154. */
  155. void Sys_Init (void)
  156. {
  157.   LARGE_INTEGER PerformanceFreq;
  158.   unsigned int  lowpart, highpart;
  159.   OSVERSIONINFO vinfo;
  160.  
  161. #ifndef SERVERONLY
  162.   // allocate a named semaphore on the client so the
  163.   // front end can tell if it is alive
  164.  
  165.   // mutex will fail if semephore allready exists
  166.     qwclsemaphore = CreateMutex(
  167.         NULL,         /* Security attributes */
  168.         0,            /* owner       */
  169.         "qwcl"); /* Semaphore name      */
  170.   if (!qwclsemaphore)
  171.     Sys_Error ("QWCL is already running on this system");
  172.   CloseHandle (qwclsemaphore);
  173.  
  174.     qwclsemaphore = CreateSemaphore(
  175.         NULL,         /* Security attributes */
  176.         0,            /* Initial count       */
  177.         1,            /* Maximum count       */
  178.         "qwcl"); /* Semaphore name      */
  179. #endif
  180.  
  181.   MaskExceptions ();
  182.   Sys_SetFPCW ();
  183.  
  184. #if 0
  185.   if (!QueryPerformanceFrequency (&PerformanceFreq))
  186.     Sys_Error ("No hardware timer available");
  187.  
  188. // get 32 out of the 64 time bits such that we have around
  189. // 1 microsecond resolution
  190.   lowpart = (unsigned int)PerformanceFreq.LowPart;
  191.   highpart = (unsigned int)PerformanceFreq.HighPart;
  192.   lowshift = 0;
  193.  
  194.   while (highpart || (lowpart > 2000000.0))
  195.   {
  196.     lowshift++;
  197.     lowpart >>= 1;
  198.     lowpart |= (highpart & 1) << 31;
  199.     highpart >>= 1;
  200.   }
  201.  
  202.   pfreq = 1.0 / (double)lowpart;
  203.  
  204.   Sys_InitFloatTime ();
  205. #endif
  206.  
  207.   // make sure the timer is high precision, otherwise
  208.   // NT gets 18ms resolution
  209.   timeBeginPeriod( 1 );
  210.  
  211.   vinfo.dwOSVersionInfoSize = sizeof(vinfo);
  212.  
  213.   if (!GetVersionEx (&vinfo))
  214.     Sys_Error ("Couldn't get OS info");
  215.  
  216.   if ((vinfo.dwMajorVersion < 4) ||
  217.     (vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
  218.   {
  219.     Sys_Error ("QuakeWorld requires at least Win95 or NT 4.0");
  220.   }
  221.   
  222.   if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  223.     WinNT = true;
  224.   else
  225.     WinNT = false;
  226. }
  227.  
  228.  
  229. void Sys_Error (char *error, ...)
  230. {
  231.   va_list   argptr;
  232.   char    text[1024], text2[1024];
  233.   DWORD   dummy;
  234.  
  235.   Host_Shutdown ();
  236.  
  237.   va_start (argptr, error);
  238.   vsprintf (text, error, argptr);
  239.   va_end (argptr);
  240.  
  241.   MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
  242.  
  243. #ifndef SERVERONLY
  244.   CloseHandle (qwclsemaphore);
  245. #endif
  246.  
  247.   exit (1);
  248. }
  249.  
  250. void Sys_Printf (char *fmt, ...)
  251. {
  252.   va_list   argptr;
  253.   char    text[1024];
  254.   DWORD   dummy;
  255.   
  256.   va_start (argptr,fmt);
  257.   vprintf (fmt, argptr);
  258.   va_end (argptr);
  259. }
  260.  
  261. void Sys_Quit (void)
  262. {
  263.   VID_ForceUnlockedAndReturnState ();
  264.  
  265.   Host_Shutdown();
  266. #ifndef SERVERONLY
  267.   if (tevent)
  268.     CloseHandle (tevent);
  269.  
  270.   if (qwclsemaphore)
  271.     CloseHandle (qwclsemaphore);
  272. #endif
  273.  
  274.   exit (0);
  275. }
  276.  
  277.  
  278. #if 0
  279. /*
  280. ================
  281. Sys_DoubleTime
  282. ================
  283. */
  284. double Sys_DoubleTime (void)
  285. {
  286.   static int      sametimecount;
  287.   static unsigned int oldtime;
  288.   static int      first = 1;
  289.   LARGE_INTEGER   PerformanceCount;
  290.   unsigned int    temp, t2;
  291.   double        time;
  292.  
  293.   Sys_PushFPCW_SetHigh ();
  294.  
  295.   QueryPerformanceCounter (&PerformanceCount);
  296.  
  297.   temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
  298.        ((unsigned int)PerformanceCount.HighPart << (32 - lowshift));
  299.  
  300.   if (first)
  301.   {
  302.     oldtime = temp;
  303.     first = 0;
  304.   }
  305.   else
  306.   {
  307.   // check for turnover or backward time
  308.     if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
  309.     {
  310.       oldtime = temp; // so we can't get stuck
  311.     }
  312.     else
  313.     {
  314.       t2 = temp - oldtime;
  315.  
  316.       time = (double)t2 * pfreq;
  317.       oldtime = temp;
  318.  
  319.       curtime += time;
  320.  
  321.       if (curtime == lastcurtime)
  322.       {
  323.         sametimecount++;
  324.  
  325.         if (sametimecount > 100000)
  326.         {
  327.           curtime += 1.0;
  328.           sametimecount = 0;
  329.         }
  330.       }
  331.       else
  332.       {
  333.         sametimecount = 0;
  334.       }
  335.  
  336.       lastcurtime = curtime;
  337.     }
  338.   }
  339.  
  340.   Sys_PopFPCW ();
  341.  
  342.     return curtime;
  343. }
  344.  
  345. /*
  346. ================
  347. Sys_InitFloatTime
  348. ================
  349. */
  350. void Sys_InitFloatTime (void)
  351. {
  352.   int   j;
  353.  
  354.   Sys_DoubleTime ();
  355.  
  356.   j = COM_CheckParm("-starttime");
  357.  
  358.   if (j)
  359.   {
  360.     curtime = (double) (Q_atof(com_argv[j+1]));
  361.   }
  362.   else
  363.   {
  364.     curtime = 0.0;
  365.   }
  366.  
  367.   lastcurtime = curtime;
  368. }
  369.  
  370. #endif
  371.  
  372. double Sys_DoubleTime (void)
  373. {
  374.   static DWORD starttime;
  375.   static qboolean first = true;
  376.   DWORD now;
  377.   double t;
  378.  
  379.   now = timeGetTime();
  380.  
  381.   if (first) {
  382.     first = false;
  383.     starttime = now;
  384.     return 0.0;
  385.   }
  386.   
  387.   if (now < starttime) // wrapped?
  388.     return (now / 1000.0) + (LONG_MAX - starttime / 1000.0);
  389.  
  390.   if (now - starttime == 0)
  391.     return 0.0;
  392.  
  393.   return (now - starttime) / 1000.0;
  394. }
  395.  
  396. char *Sys_ConsoleInput (void)
  397. {
  398.   static char text[256];
  399.   static int    len;
  400.   INPUT_RECORD  recs[1024];
  401.   int   count;
  402.   int   i, dummy;
  403.   int   ch, numread, numevents;
  404.   HANDLE  th;
  405.   char  *clipText, *textCopied;
  406.  
  407.   for ( ;; )
  408.   {
  409.     if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
  410.       Sys_Error ("Error getting # of console events");
  411.  
  412.     if (numevents <= 0)
  413.       break;
  414.  
  415.     if (!ReadConsoleInput(hinput, recs, 1, &numread))
  416.       Sys_Error ("Error reading console input");
  417.  
  418.     if (numread != 1)
  419.       Sys_Error ("Couldn't read console input");
  420.  
  421.     if (recs[0].EventType == KEY_EVENT)
  422.     {
  423.       if (!recs[0].Event.KeyEvent.bKeyDown)
  424.       {
  425.         ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
  426.  
  427.         switch (ch)
  428.         {
  429.           case '\r':
  430.             WriteFile(houtput, "\r\n", 2, &dummy, NULL);  
  431.  
  432.             if (len)
  433.             {
  434.               text[len] = 0;
  435.               len = 0;
  436.               return text;
  437.             }
  438.             break;
  439.  
  440.           case '\b':
  441.             WriteFile(houtput, "\b \b", 3, &dummy, NULL); 
  442.             if (len)
  443.             {
  444.               len--;
  445.               putch('\b');
  446.             }
  447.             break;
  448.  
  449.           default:
  450.             Con_Printf("Stupid: %d\n", recs[0].Event.KeyEvent.dwControlKeyState);
  451.             if (((ch=='V' || ch=='v') && (recs[0].Event.KeyEvent.dwControlKeyState & 
  452.               (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))) || ((recs[0].Event.KeyEvent.dwControlKeyState 
  453.               & SHIFT_PRESSED) && (recs[0].Event.KeyEvent.wVirtualKeyCode
  454.               ==VK_INSERT))) {
  455.               if (OpenClipboard(NULL)) {
  456.                 th = GetClipboardData(CF_TEXT);
  457.                 if (th) {
  458.                   clipText = GlobalLock(th);
  459.                   if (clipText) {
  460.                     textCopied = malloc(GlobalSize(th)+1);
  461.                     strcpy(textCopied, clipText);
  462. /* Substitutes a NULL for every token */strtok(textCopied, "\n\r\b");
  463.                     i = strlen(textCopied);
  464.                     if (i+len>=256)
  465.                       i=256-len;
  466.                     if (i>0) {
  467.                       textCopied[i]=0;
  468.                       text[len]=0;
  469.                       strcat(text, textCopied);
  470.                       len+=dummy;
  471.                       WriteFile(houtput, textCopied, i, &dummy, NULL);
  472.                     }
  473.                     free(textCopied);
  474.                   }
  475.                   GlobalUnlock(th);
  476.                 }
  477.                 CloseClipboard();
  478.               }
  479.             } else if (ch >= ' ')
  480.             {
  481.               WriteFile(houtput, &ch, 1, &dummy, NULL); 
  482.               text[len] = ch;
  483.               len = (len + 1) & 0xff;
  484.             }
  485.  
  486.             break;
  487.  
  488.         }
  489.       }
  490.     }
  491.   }
  492.  
  493.   return NULL;
  494. }
  495.  
  496. void Sys_Sleep (void)
  497. {
  498. }
  499.  
  500.  
  501. void Sys_SendKeyEvents (void)
  502. {
  503.     MSG        msg;
  504.  
  505.   while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
  506.   {
  507.   // we always update if there are any event, even if we're paused
  508.     scr_skipupdate = 0;
  509.  
  510.     if (!GetMessage (&msg, NULL, 0, 0))
  511.       Sys_Quit ();
  512.         TranslateMessage (&msg);
  513.         DispatchMessage (&msg);
  514.   }
  515. }
  516.  
  517.  
  518.  
  519. /*
  520. ==============================================================================
  521.  
  522.  WINDOWS CRAP
  523.  
  524. ==============================================================================
  525. */
  526.  
  527. /*
  528. ==================
  529. WinMain
  530. ==================
  531. */
  532. void SleepUntilInput (int time)
  533. {
  534.  
  535.   MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT);
  536. }
  537.  
  538.  
  539.  
  540. /*
  541. ==================
  542. WinMain
  543. ==================
  544. */
  545. HINSTANCE global_hInstance;
  546. int     global_nCmdShow;
  547. char    *argv[MAX_NUM_ARGVS];
  548. static char *empty_string = "";
  549. HWND    hwnd_dialog;
  550.  
  551.  
  552. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  553. {
  554.     MSG       msg;
  555.   quakeparms_t  parms;
  556.   double      time, oldtime, newtime;
  557.   MEMORYSTATUS  lpBuffer;
  558.   static  char  cwd[1024];
  559.   int       t;
  560.   RECT      rect;
  561.  
  562.     /* previous instances do not exist in Win32 */
  563.     if (hPrevInstance)
  564.         return 0;
  565.  
  566.   global_hInstance = hInstance;
  567.   global_nCmdShow = nCmdShow;
  568.  
  569.   lpBuffer.dwLength = sizeof(MEMORYSTATUS);
  570.   GlobalMemoryStatus (&lpBuffer);
  571.  
  572.   if (!GetCurrentDirectory (sizeof(cwd), cwd))
  573.     Sys_Error ("Couldn't determine current directory");
  574.  
  575.   if (cwd[Q_strlen(cwd)-1] == '/')
  576.     cwd[Q_strlen(cwd)-1] = 0;
  577.  
  578.   parms.basedir = cwd;
  579.   parms.cachedir = NULL;
  580.  
  581.   parms.argc = 1;
  582.   argv[0] = empty_string;
  583.  
  584.   while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
  585.   {
  586.     while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
  587.       lpCmdLine++;
  588.  
  589.     if (*lpCmdLine)
  590.     {
  591.       argv[parms.argc] = lpCmdLine;
  592.       parms.argc++;
  593.  
  594.       while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
  595.         lpCmdLine++;
  596.  
  597.       if (*lpCmdLine)
  598.       {
  599.         *lpCmdLine = 0;
  600.         lpCmdLine++;
  601.       }
  602.       
  603.     }
  604.   }
  605.  
  606.   parms.argv = argv;
  607.  
  608.   COM_InitArgv (parms.argc, parms.argv);
  609.  
  610.   parms.argc = com_argc;
  611.   parms.argv = com_argv;
  612.  
  613.   hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
  614.  
  615.   if (hwnd_dialog)
  616.   {
  617.     if (GetWindowRect (hwnd_dialog, &rect))
  618.     {
  619.       if (rect.left > (rect.top * 2))
  620.       {
  621.         SetWindowPos (hwnd_dialog, 0,
  622.           (rect.left / 2) - ((rect.right - rect.left) / 2),
  623.           rect.top, 0, 0,
  624.           SWP_NOZORDER | SWP_NOSIZE);
  625.       }
  626.     }
  627.  
  628.     ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
  629.     UpdateWindow (hwnd_dialog);
  630.     SetForegroundWindow (hwnd_dialog);
  631.   }
  632.  
  633. // take the greater of all the available memory or half the total memory,
  634. // but at least 8 Mb and no more than 16 Mb, unless they explicitly
  635. // request otherwise
  636.   parms.memsize = lpBuffer.dwAvailPhys;
  637.  
  638.   if (parms.memsize < MINIMUM_WIN_MEMORY)
  639.     parms.memsize = MINIMUM_WIN_MEMORY;
  640.  
  641.   if (parms.memsize < (lpBuffer.dwTotalPhys >> 1))
  642.     parms.memsize = lpBuffer.dwTotalPhys >> 1;
  643.  
  644.   if (parms.memsize > MAXIMUM_WIN_MEMORY)
  645.     parms.memsize = MAXIMUM_WIN_MEMORY;
  646.  
  647.   if (COM_CheckParm ("-heapsize"))
  648.   {
  649.     t = COM_CheckParm("-heapsize") + 1;
  650.  
  651.     if (t < com_argc)
  652.       parms.memsize = Q_atoi (com_argv[t]) * 1024;
  653.   }
  654.  
  655.   parms.membase = malloc (parms.memsize);
  656.  
  657.   if (!parms.membase)
  658.     Sys_Error ("Not enough memory free; check disk space\n");
  659.  
  660.   tevent = CreateEvent(NULL, FALSE, FALSE, NULL);
  661.  
  662.   if (!tevent)
  663.     Sys_Error ("Couldn't create event");
  664.  
  665.   Sys_Init ();
  666.  
  667. // because sound is off until we become active
  668.   S_BlockSound ();
  669.  
  670.   Sys_Printf ("Host_Init\n");
  671.   Host_Init (&parms);
  672.  
  673.   oldtime = Sys_DoubleTime ();
  674.  
  675.     /* main window message loop */
  676.   while (1)
  677.   {
  678.   // yield the CPU for a little while when paused, minimized, or not the focus
  679.     if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing)
  680.     {
  681.       SleepUntilInput (PAUSE_SLEEP);
  682.       scr_skipupdate = 1;   // no point in bothering to draw
  683.     }
  684.     else if (!ActiveApp && !DDActive)
  685.     {
  686.       SleepUntilInput (NOT_FOCUS_SLEEP);
  687.     }
  688.  
  689.     newtime = Sys_DoubleTime ();
  690.     time = newtime - oldtime;
  691.     Host_Frame (time);
  692.     oldtime = newtime;
  693.   }
  694.  
  695.     /* return success of application */
  696.     return TRUE;
  697. }
  698.  
  699.