]> icculus.org git repositories - divverent/darkplaces.git/blob - sys_linux.c
in "bf", make alpha and alphafade optional (if left out, they will default to the...
[divverent/darkplaces.git] / sys_linux.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
16 #ifdef WIN32
17 cvar_t sys_usetimegettime = {CVAR_SAVE, "sys_usetimegettime", "1", "use windows timeGetTime function (which has issues on some motherboards) for timing rather than QueryPerformanceCounter timer (which has issues on multicore/multiprocessor machines and processors which are designed to conserve power)"};
18 #else
19 # ifndef MACOSX
20 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)"};
21 # endif
22 #endif
23
24
25
26 // =======================================================================
27 // General routines
28 // =======================================================================
29 void Sys_Shutdown (void)
30 {
31 #ifndef WIN32
32         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
33 #endif
34         fflush(stdout);
35 }
36
37 void Sys_Error (const char *error, ...)
38 {
39         va_list argptr;
40         char string[MAX_INPUTLINE];
41
42 // change stdin to non blocking
43 #ifndef WIN32
44         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
45 #endif
46
47         va_start (argptr,error);
48         dpvsnprintf (string, sizeof (string), error, argptr);
49         va_end (argptr);
50
51         Con_Printf ("Quake Error: %s\n", string);
52
53         Host_Shutdown ();
54         exit (1);
55 }
56
57 void Sys_PrintToTerminal(const char *text)
58 {
59 #ifndef WIN32
60         // BUG: for some reason, NDELAY also affects stdout (1) when used on stdin (0).
61         int origflags = fcntl (1, F_GETFL, 0);
62         fcntl (1, F_SETFL, origflags & ~FNDELAY);
63 #else
64 #define write _write
65 #endif
66         while(*text)
67         {
68                 int written = (int)write(1, text, (int)strlen(text));
69                 if(written <= 0)
70                         break; // sorry, I cannot do anything about this error - without an output
71                 text += written;
72         }
73 #ifndef WIN32
74         fcntl (1, F_SETFL, origflags);
75 #endif
76         //fprintf(stdout, "%s", text);
77 }
78
79 double Sys_DoubleTime (void)
80 {
81         static int first = true;
82         static double oldtime = 0.0, curtime = 0.0;
83         double newtime;
84 #ifdef WIN32
85 #include <mmsystem.h>
86         // LordHavoc: note to people modifying this code, DWORD is specifically defined as an unsigned 32bit number, therefore the 65536.0 * 65536.0 is fine.
87         if (sys_usetimegettime.integer)
88         {
89                 static int firsttimegettime = true;
90                 // timeGetTime
91                 // platform:
92                 // Windows 95/98/ME/NT/2000/XP
93                 // features:
94                 // reasonable accuracy (millisecond)
95                 // issues:
96                 // wraps around every 47 days or so (but this is non-fatal to us, odd times are rejected, only causes a one frame stutter)
97
98                 // make sure the timer is high precision, otherwise different versions of windows have varying accuracy
99                 if (firsttimegettime)
100                 {
101                         timeBeginPeriod (1);
102                         firsttimegettime = false;
103                 }
104
105                 newtime = (double) timeGetTime () / 1000.0;
106         }
107         else
108         {
109                 // QueryPerformanceCounter
110                 // platform:
111                 // Windows 95/98/ME/NT/2000/XP
112                 // features:
113                 // very accurate (CPU cycles)
114                 // known issues:
115                 // does not necessarily match realtime too well (tends to get faster and faster in win98)
116                 // wraps around occasionally on some platforms (depends on CPU speed and probably other unknown factors)
117                 double timescale;
118                 LARGE_INTEGER PerformanceFreq;
119                 LARGE_INTEGER PerformanceCount;
120
121                 if (!QueryPerformanceFrequency (&PerformanceFreq))
122                 {
123                         Con_Printf ("No hardware timer available\n");
124                         // fall back to timeGetTime
125                         Cvar_SetValueQuick(&sys_usetimegettime, true);
126                         return Sys_DoubleTime();
127                 }
128                 QueryPerformanceCounter (&PerformanceCount);
129
130                 #ifdef __BORLANDC__
131                 timescale = 1.0 / ((double) PerformanceFreq.u.LowPart + (double) PerformanceFreq.u.HighPart * 65536.0 * 65536.0);
132                 newtime = ((double) PerformanceCount.u.LowPart + (double) PerformanceCount.u.HighPart * 65536.0 * 65536.0) * timescale;
133                 #else
134                 timescale = 1.0 / ((double) PerformanceFreq.LowPart + (double) PerformanceFreq.HighPart * 65536.0 * 65536.0);
135                 newtime = ((double) PerformanceCount.LowPart + (double) PerformanceCount.HighPart * 65536.0 * 65536.0) * timescale;
136                 #endif
137         }
138 #else
139 # ifndef MACOSX
140         if (sys_useclockgettime.integer)
141         {
142                 struct timespec ts;
143 #  ifdef SUNOS
144                 clock_gettime(CLOCK_HIGHRES, &ts);
145 #  else
146                 clock_gettime(CLOCK_MONOTONIC, &ts);
147 #  endif
148                 newtime = (double) ts.tv_sec + ts.tv_nsec / 1000000000.0;
149         }
150         else
151 # endif
152         {
153                 struct timeval tp;
154                 gettimeofday(&tp, NULL);
155                 newtime = (double) tp.tv_sec + tp.tv_usec / 1000000.0;
156         }
157 #endif
158
159         if (first)
160         {
161                 first = false;
162                 oldtime = newtime;
163         }
164
165         if (newtime < oldtime)
166         {
167                 // warn if it's significant
168                 if (newtime - oldtime < -0.01)
169                         Con_Printf("Sys_DoubleTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
170         }
171         else if (newtime > oldtime + 1800)
172         {
173                 Con_Printf("Sys_DoubleTime: time stepped forward (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
174         }
175         else
176                 curtime += newtime - oldtime;
177         oldtime = newtime;
178
179         return curtime;
180 }
181
182 char *Sys_ConsoleInput(void)
183 {
184         if (cls.state == ca_dedicated)
185         {
186                 static char text[MAX_INPUTLINE];
187                 static unsigned int len = 0;
188 #ifdef WIN32
189                 int c;
190
191                 // read a line out
192                 while (_kbhit ())
193                 {
194                         c = _getch ();
195                         if (c == '\r')
196                         {
197                                 text[len] = '\0';
198                                 _putch ('\n');
199                                 len = 0;
200                                 return text;
201                         }
202                         if (c == '\b')
203                         {
204                                 if (len)
205                                 {
206                                         _putch (c);
207                                         _putch (' ');
208                                         _putch (c);
209                                         len--;
210                                 }
211                                 continue;
212                         }
213                         if (len < sizeof (text) - 1)
214                         {
215                                 _putch (c);
216                                 text[len] = c;
217                                 len++;
218                         }
219                 }
220 #else
221                 fd_set fdset;
222                 struct timeval timeout;
223                 FD_ZERO(&fdset);
224                 FD_SET(0, &fdset); // stdin
225                 timeout.tv_sec = 0;
226                 timeout.tv_usec = 0;
227                 if (select (1, &fdset, NULL, NULL, &timeout) != -1 && FD_ISSET(0, &fdset))
228                 {
229                         len = read (0, text, sizeof(text));
230                         if (len >= 1)
231                         {
232                                 // rip off the \n and terminate
233                                 text[len-1] = 0;
234                                 return text;
235                         }
236                 }
237 #endif
238         }
239         return NULL;
240 }
241
242 void Sys_Sleep(int microseconds)
243 {
244 #ifdef WIN32
245         Sleep(microseconds / 1000);
246 #else
247         usleep(microseconds);
248 #endif
249 }
250
251 char *Sys_GetClipboardData (void)
252 {
253         return NULL;
254 }
255
256 void Sys_InitConsole (void)
257 {
258 }
259
260 void Sys_Init_Commands (void)
261 {
262 #ifdef WIN32
263         Cvar_RegisterVariable(&sys_usetimegettime);
264 #else
265 # ifndef MACOSX
266         Cvar_RegisterVariable(&sys_useclockgettime);
267 # endif
268 #endif
269 }
270
271 int main (int argc, char **argv)
272 {
273         signal(SIGFPE, SIG_IGN);
274
275         com_argc = argc;
276         com_argv = (const char **)argv;
277
278 #ifndef WIN32
279         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
280 #endif
281
282         Host_Main();
283
284         return 0;
285 }