Merge branch 'master' into blub/cmd_unset
[divverent/darkplaces.git] / sys_sdl.c
1 #include "quakedef.h"
2
3 #ifdef WIN32
4 #include <io.h>
5 #include "conio.h"
6 #else
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <sys/time.h>
10 #include <time.h>
11 #endif
12
13 #include <signal.h>
14
15 #include <SDL.h>
16
17 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."};
18 static unsigned long benchmark_time;
19
20 #ifndef WIN32
21 # ifndef MACOSX
22 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)"};
23 # endif
24 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)"};
25 #endif
26
27
28 // =======================================================================
29 // General routines
30 // =======================================================================
31
32 void Sys_Shutdown (void)
33 {
34 #ifndef WIN32
35         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
36 #endif
37         fflush(stdout);
38         SDL_Quit();
39 }
40
41
42 void Sys_Error (const char *error, ...)
43 {
44         va_list argptr;
45         char string[MAX_INPUTLINE];
46
47 // change stdin to non blocking
48 #ifndef WIN32
49         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
50 #endif
51
52         va_start (argptr,error);
53         dpvsnprintf (string, sizeof (string), error, argptr);
54         va_end (argptr);
55
56         Con_Printf ("Quake Error: %s\n", string);
57
58         Host_Shutdown ();
59         exit (1);
60 }
61
62 void Sys_PrintToTerminal(const char *text)
63 {
64 #ifndef WIN32
65         // BUG: for some reason, NDELAY also affects stdout (1) when used on stdin (0).
66         int origflags = fcntl (1, F_GETFL, 0);
67         fcntl (1, F_SETFL, origflags & ~FNDELAY);
68 #else
69 #define write _write
70 #endif
71         while(*text)
72         {
73                 int written = (int)write(1, text, (int)strlen(text));
74                 if(written <= 0)
75                         break; // sorry, I cannot do anything about this error - without an output
76                 text += written;
77         }
78 #ifndef WIN32
79         fcntl (1, F_SETFL, origflags);
80 #endif
81         //fprintf(stdout, "%s", text);
82 }
83
84 double Sys_DoubleTime (void)
85 {
86         static int first = true;
87         static double oldtime = 0.0, curtime = 0.0;
88         double newtime;
89         if(sys_usenoclockbutbenchmark.integer)
90         {
91                 benchmark_time += 1;
92                 return ((double) benchmark_time) / 1e6;
93         }
94         // use higher precision timers on some platforms
95 #ifndef WIN32
96 # ifndef MACOSX
97         if (sys_useclockgettime.integer)
98         {
99                 struct timespec ts;
100 #  ifdef SUNOS
101                 clock_gettime(CLOCK_HIGHRES, &ts);
102 #  else
103                 clock_gettime(CLOCK_MONOTONIC, &ts);
104 #  endif
105                 newtime = (double) ts.tv_sec + ts.tv_nsec / 1000000000.0;
106         }
107         else if (sys_usegettimeofday.integer)
108 # endif
109         {
110                 struct timeval tp;
111                 gettimeofday(&tp, NULL);
112                 newtime = (double) tp.tv_sec + tp.tv_usec / 1000000.0;
113         }
114         else
115 #endif
116         {
117                 newtime = (double) SDL_GetTicks() / 1000.0;
118         }
119
120
121         if (first)
122         {
123                 first = false;
124                 oldtime = newtime;
125         }
126
127         if (newtime < oldtime)
128         {
129                 // warn if it's significant
130                 if (newtime - oldtime < -0.01)
131                         Con_Printf("Sys_DoubleTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
132         }
133         else if (newtime > oldtime + 1800)
134         {
135                 Con_Printf("Sys_DoubleTime: time stepped forward (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
136         }
137         else
138                 curtime += newtime - oldtime;
139         oldtime = newtime;
140
141         return curtime;
142 }
143
144 char *Sys_ConsoleInput(void)
145 {
146         if (cls.state == ca_dedicated)
147         {
148                 static char text[MAX_INPUTLINE];
149                 int len = 0;
150 #ifdef WIN32
151                 int c;
152
153                 // read a line out
154                 while (_kbhit ())
155                 {
156                         c = _getch ();
157                         _putch (c);
158                         if (c == '\r')
159                         {
160                                 text[len] = 0;
161                                 _putch ('\n');
162                                 len = 0;
163                                 return text;
164                         }
165                         if (c == 8)
166                         {
167                                 if (len)
168                                 {
169                                         _putch (' ');
170                                         _putch (c);
171                                         len--;
172                                         text[len] = 0;
173                                 }
174                                 continue;
175                         }
176                         text[len] = c;
177                         len++;
178                         text[len] = 0;
179                         if (len == sizeof (text))
180                                 len = 0;
181                 }
182 #else
183                 fd_set fdset;
184                 struct timeval timeout;
185                 FD_ZERO(&fdset);
186                 FD_SET(0, &fdset); // stdin
187                 timeout.tv_sec = 0;
188                 timeout.tv_usec = 0;
189                 if (select (1, &fdset, NULL, NULL, &timeout) != -1 && FD_ISSET(0, &fdset))
190                 {
191                         len = read (0, text, sizeof(text));
192                         if (len >= 1)
193                         {
194                                 // rip off the \n and terminate
195                                 text[len-1] = 0;
196                                 return text;
197                         }
198                 }
199 #endif
200         }
201         return NULL;
202 }
203
204 void Sys_Sleep(int microseconds)
205 {
206         if(sys_usenoclockbutbenchmark.integer)
207         {
208                 benchmark_time += microseconds;
209                 return;
210         }
211         SDL_Delay(microseconds / 1000);
212 }
213
214 char *Sys_GetClipboardData (void)
215 {
216 #ifdef WIN32
217         char *data = NULL;
218         char *cliptext;
219
220         if (OpenClipboard (NULL) != 0)
221         {
222                 HANDLE hClipboardData;
223
224                 if ((hClipboardData = GetClipboardData (CF_TEXT)) != 0)
225                 {
226                         if ((cliptext = (char *)GlobalLock (hClipboardData)) != 0)
227                         {
228                                 size_t allocsize;
229                                 allocsize = GlobalSize (hClipboardData) + 1;
230                                 data = (char *)Z_Malloc (allocsize);
231                                 strlcpy (data, cliptext, allocsize);
232                                 GlobalUnlock (hClipboardData);
233                         }
234                 }
235                 CloseClipboard ();
236         }
237         return data;
238 #else
239         return NULL;
240 #endif
241 }
242
243 void Sys_InitConsole (void)
244 {
245 }
246
247 void Sys_Init_Commands (void)
248 {
249         Cvar_RegisterVariable(&sys_usenoclockbutbenchmark);
250 #ifndef WIN32
251 # ifndef MACOSX
252         Cvar_RegisterVariable(&sys_useclockgettime);
253 # endif
254         Cvar_RegisterVariable(&sys_usegettimeofday);
255 #endif
256 }
257
258 int main (int argc, char *argv[])
259 {
260         signal(SIGFPE, SIG_IGN);
261
262         com_argc = argc;
263         com_argv = (const char **)argv;
264
265 #ifndef WIN32
266         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
267 #endif
268
269         // we don't know which systems we'll want to init, yet...
270         SDL_Init(0);
271
272         Host_Main();
273
274         return 0;
275 }