]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sys_sdl.c
added linux timing code to SDL client for more accurate r_speeds reports
[xonotic/darkplaces.git] / sys_sdl.c
index be0f67df3a1f7f2d3f8000afa03cd8a16ec97589..4b45b6de8e4a67c738523e39df90c1f9ab6c3ca6 100644 (file)
--- a/sys_sdl.c
+++ b/sys_sdl.c
@@ -1,3 +1,4 @@
+#include "quakedef.h"
 
 #ifdef WIN32
 #include <io.h>
@@ -6,14 +7,24 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/time.h>
+#include <time.h>
 #endif
 
 #include <signal.h>
 
-#include "quakedef.h"
-
 #include <SDL.h>
 
+cvar_t sys_usenoclockbutbenchmark = {CVAR_SAVE, "sys_usenoclockbutbenchmark", "0", "don't use ANY real timing, and simulate a clock (for benchmarking); the game then runs as fast as possible. Run a QC mod with bots that does some stuff, then does a quit at the end, to benchmark a server. NEVER do this on a public server."};
+static unsigned long benchmark_time;
+
+#ifndef WIN32
+# ifndef MACOSX
+cvar_t sys_useclockgettime = {CVAR_SAVE, "sys_useclockgettime", "0", "use POSIX clock_gettime function (which has issues if the system clock speed is far off, as it can't get fixed by NTP) for timing rather than gettimeofday (which has issues if the system time is stepped by ntpdate, or apparently on some Xen installations)"};
+# endif
+cvar_t sys_usegettimeofday = {CVAR_SAVE, "sys_usegettimeofday", "0", "use gettimeofday (which has issues if the system time is stepped by ntpdate, or apparently on some Xen installations) which has microsecond precision rather than SDL_GetTicks (which has only millisecond precision)"};
+#endif
+
+
 // =======================================================================
 // General routines
 // =======================================================================
@@ -54,6 +65,8 @@ void Sys_PrintToTerminal(const char *text)
        // BUG: for some reason, NDELAY also affects stdout (1) when used on stdin (0).
        int origflags = fcntl (1, F_GETFL, 0);
        fcntl (1, F_SETFL, origflags & ~FNDELAY);
+#else
+#define write _write
 #endif
        while(*text)
        {
@@ -73,7 +86,36 @@ double Sys_DoubleTime (void)
        static int first = true;
        static double oldtime = 0.0, curtime = 0.0;
        double newtime;
-       newtime = (double) SDL_GetTicks() / 1000.0;
+       if(sys_usenoclockbutbenchmark.integer)
+       {
+               benchmark_time += 1;
+               return ((double) benchmark_time) / 1e6;
+       }
+       // use higher precision timers on some platforms
+#ifndef WIN32
+# ifndef MACOSX
+       if (sys_useclockgettime.integer)
+       {
+               struct timespec ts;
+#  ifdef SUNOS
+               clock_gettime(CLOCK_HIGHRES, &ts);
+#  else
+               clock_gettime(CLOCK_MONOTONIC, &ts);
+#  endif
+               newtime = (double) ts.tv_sec + ts.tv_nsec / 1000000000.0;
+       }
+       else if (sys_usegettimeofday.integer)
+# endif
+       {
+               struct timeval tp;
+               gettimeofday(&tp, NULL);
+               newtime = (double) tp.tv_sec + tp.tv_usec / 1000000.0;
+       }
+       else
+#endif
+       {
+               newtime = (double) SDL_GetTicks() / 1000.0;
+       }
 
 
        if (first)
@@ -88,6 +130,10 @@ double Sys_DoubleTime (void)
                if (newtime - oldtime < -0.01)
                        Con_Printf("Sys_DoubleTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
        }
+       else if (newtime > oldtime + 1800)
+       {
+               Con_Printf("Sys_DoubleTime: time stepped forward (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
+       }
        else
                curtime += newtime - oldtime;
        oldtime = newtime;
@@ -108,11 +154,11 @@ char *Sys_ConsoleInput(void)
                while (_kbhit ())
                {
                        c = _getch ();
-                       putch (c);
+                       _putch (c);
                        if (c == '\r')
                        {
                                text[len] = 0;
-                               putch ('\n');
+                               _putch ('\n');
                                len = 0;
                                return text;
                        }
@@ -120,8 +166,8 @@ char *Sys_ConsoleInput(void)
                        {
                                if (len)
                                {
-                                       putch (' ');
-                                       putch (c);
+                                       _putch (' ');
+                                       _putch (c);
                                        len--;
                                        text[len] = 0;
                                }
@@ -155,11 +201,14 @@ char *Sys_ConsoleInput(void)
        return NULL;
 }
 
-void Sys_Sleep(int milliseconds)
+void Sys_Sleep(int microseconds)
 {
-       if (milliseconds < 1)
-               milliseconds = 1;
-       SDL_Delay(milliseconds);
+       if(sys_usenoclockbutbenchmark.integer)
+       {
+               benchmark_time += microseconds;
+               return;
+       }
+       SDL_Delay(microseconds / 1000);
 }
 
 char *Sys_GetClipboardData (void)
@@ -174,10 +223,12 @@ char *Sys_GetClipboardData (void)
 
                if ((hClipboardData = GetClipboardData (CF_TEXT)) != 0)
                {
-                       if ((cliptext = GlobalLock (hClipboardData)) != 0)
+                       if ((cliptext = (char *)GlobalLock (hClipboardData)) != 0)
                        {
-                               data = malloc (GlobalSize(hClipboardData)+1);
-                               strcpy (data, cliptext);
+                               size_t allocsize;
+                               allocsize = GlobalSize (hClipboardData) + 1;
+                               data = (char *)Z_Malloc (allocsize);
+                               strlcpy (data, cliptext, allocsize);
                                GlobalUnlock (hClipboardData);
                        }
                }
@@ -195,12 +246,17 @@ void Sys_InitConsole (void)
 
 void Sys_Init_Commands (void)
 {
+       Cvar_RegisterVariable(&sys_usenoclockbutbenchmark);
+#ifndef WIN32
+# ifndef MACOSX
+       Cvar_RegisterVariable(&sys_useclockgettime);
+# endif
+       Cvar_RegisterVariable(&sys_usegettimeofday);
+#endif
 }
 
 int main (int argc, char *argv[])
 {
-       double frameoldtime, framenewtime;
-
        signal(SIGFPE, SIG_IGN);
 
        com_argc = argc;
@@ -210,17 +266,10 @@ int main (int argc, char *argv[])
        fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
 #endif
 
-       Host_Init();
+       // we don't know which systems we'll want to init, yet...
+       SDL_Init(0);
 
-       frameoldtime = Sys_DoubleTime () - 0.1;
-       while (1)
-       {
-               // find time spent rendering last frame
-               framenewtime = Sys_DoubleTime ();
-
-               Host_Frame (framenewtime - frameoldtime);
+       Host_Main();
 
-               frameoldtime = framenewtime;
-       }
        return 0;
 }