darkplaces-dedicated.exe now builds
[divverent/darkplaces.git] / sys_linux.c
1
2 #ifdef WIN32
3 #include "conio.h"
4 #else
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/time.h>
8 #include <dlfcn.h>
9 #endif
10
11 #include <signal.h>
12
13 #include "quakedef.h"
14
15
16 #ifdef WIN32
17 cvar_t sys_usetimegettime = {CVAR_SAVE, "sys_usetimegettime", "1"};
18 #endif
19
20 /*
21 ===============================================================================
22
23 DLL MANAGEMENT
24
25 ===============================================================================
26 */
27
28 dllhandle_t Sys_LoadLibrary (const char* name)
29 {
30 #ifdef WIN32
31         return LoadLibrary (name);
32 #else
33         return dlopen (name, RTLD_LAZY);
34 #endif
35 }
36
37 void Sys_UnloadLibrary (dllhandle_t handle)
38 {
39 #ifdef WIN32
40         FreeLibrary (handle);
41 #else
42         dlclose (handle);
43 #endif
44 }
45
46 void* Sys_GetProcAddress (dllhandle_t handle, const char* name)
47 {
48 #ifdef WIN32
49         return (void *)GetProcAddress (handle, name);
50 #else
51         return (void *)dlsym (handle, name);
52 #endif
53 }
54
55
56 // =======================================================================
57 // General routines
58 // =======================================================================
59
60 void Sys_Quit (void)
61 {
62         Host_Shutdown();
63 #ifndef WIN32
64         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
65 #endif
66         fflush(stdout);
67         exit(0);
68 }
69
70 void Sys_Error (const char *error, ...)
71 {
72         va_list argptr;
73         char string[1024];
74
75 // change stdin to non blocking
76 #ifndef WIN32
77         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
78 #endif
79
80         va_start (argptr,error);
81         vsprintf (string,error,argptr);
82         va_end (argptr);
83         fprintf(stderr, "Error: %s\n", string);
84
85         Host_Shutdown ();
86         exit (1);
87
88 }
89
90 double Sys_DoubleTime (void)
91 {
92         static int first = true;
93         static double oldtime = 0.0, curtime = 0.0;
94         double newtime;
95 #ifdef WIN32
96         // LordHavoc: note to people modifying this code, DWORD is specifically defined as an unsigned 32bit number, therefore the 65536.0 * 65536.0 is fine.
97         if (sys_usetimegettime.integer)
98         {
99                 static int firsttimegettime = true;
100                 // timeGetTime
101                 // platform:
102                 // Windows 95/98/ME/NT/2000/XP
103                 // features:
104                 // reasonable accuracy (millisecond)
105                 // issues:
106                 // wraps around every 47 days or so (but this is non-fatal to us, odd times are rejected, only causes a one frame stutter)
107
108                 // make sure the timer is high precision, otherwise different versions of windows have varying accuracy
109                 if (firsttimegettime)
110                 {
111                         timeBeginPeriod (1);
112                         firsttimegettime = false;
113                 }
114
115                 newtime = (double) timeGetTime () / 1000.0;
116         }
117         else
118         {
119                 // QueryPerformanceCounter
120                 // platform:
121                 // Windows 95/98/ME/NT/2000/XP
122                 // features:
123                 // very accurate (CPU cycles)
124                 // known issues:
125                 // does not necessarily match realtime too well (tends to get faster and faster in win98)
126                 // wraps around occasionally on some platforms (depends on CPU speed and probably other unknown factors)
127                 double timescale;
128                 LARGE_INTEGER PerformanceFreq;
129                 LARGE_INTEGER PerformanceCount;
130
131                 if (!QueryPerformanceFrequency (&PerformanceFreq))
132                         Sys_Error ("No hardware timer available");
133                 QueryPerformanceCounter (&PerformanceCount);
134
135                 #ifdef __BORLANDC__
136                 timescale = 1.0 / ((double) PerformanceFreq.u.LowPart + (double) PerformanceFreq.u.HighPart * 65536.0 * 65536.0);
137                 newtime = ((double) PerformanceCount.u.LowPart + (double) PerformanceCount.u.HighPart * 65536.0 * 65536.0) * timescale;
138                 #else
139                 timescale = 1.0 / ((double) PerformanceFreq.LowPart + (double) PerformanceFreq.HighPart * 65536.0 * 65536.0);
140                 newtime = ((double) PerformanceCount.LowPart + (double) PerformanceCount.HighPart * 65536.0 * 65536.0) * timescale;
141                 #endif
142         }
143 #else
144         struct timeval tp;
145         gettimeofday(&tp, NULL);
146         newtime = (double) tp.tv_sec + tp.tv_usec / 1000000.0;
147 #endif
148
149         if (first)
150         {
151                 first = false;
152                 oldtime = newtime;
153         }
154
155         if (newtime < oldtime)
156         {
157                 // warn if it's significant
158                 if (newtime - oldtime < -0.01)
159                         Con_Printf("Sys_DoubleTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
160         }
161         else
162                 curtime += newtime - oldtime;
163         oldtime = newtime;
164
165         return curtime;
166 }
167
168 char *Sys_ConsoleInput(void)
169 {
170         if (cls.state == ca_dedicated)
171         {
172                 static char text[256];
173                 int len;
174 #ifdef WIN32
175                 int c;
176
177                 // read a line out
178                 while (_kbhit ())
179                 {
180                         c = _getch ();
181                         putch (c);
182                         if (c == '\r')
183                         {
184                                 text[len] = 0;
185                                 putch ('\n');
186                                 len = 0;
187                                 return text;
188                         }
189                         if (c == 8)
190                         {
191                                 if (len)
192                                 {
193                                         putch (' ');
194                                         putch (c);
195                                         len--;
196                                         text[len] = 0;
197                                 }
198                                 continue;
199                         }
200                         text[len] = c;
201                         len++;
202                         text[len] = 0;
203                         if (len == sizeof (text))
204                                 len = 0;
205                 }
206 #else
207                 fd_set fdset;
208                 struct timeval timeout;
209                 FD_ZERO(&fdset);
210                 FD_SET(0, &fdset); // stdin
211                 timeout.tv_sec = 0;
212                 timeout.tv_usec = 0;
213                 if (select (1, &fdset, NULL, NULL, &timeout) != -1 && FD_ISSET(0, &fdset))
214                 {
215                         len = read (0, text, sizeof(text));
216                         if (len >= 1)
217                         {
218                                 // rip off the \n and terminate
219                                 text[len-1] = 0;
220                                 return text;
221                         }
222                 }
223 #endif
224         }
225         return NULL;
226 }
227
228 void Sys_Sleep(void)
229 {
230 #ifdef WIN32
231         Sleep (1);
232 #else
233         usleep(1);
234 #endif
235 }
236
237 int main (int argc, const char **argv)
238 {
239         double frameoldtime, framenewtime;
240
241         signal(SIGFPE, SIG_IGN);
242
243         com_argc = argc;
244         com_argv = argv;
245
246 #ifndef WIN32
247         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
248 #endif
249
250         Sys_Shared_EarlyInit();
251
252         Host_Init();
253
254         Sys_Shared_LateInit();
255
256         frameoldtime = Sys_DoubleTime () - 0.1;
257         while (1)
258         {
259                 // find time spent rendering last frame
260                 framenewtime = Sys_DoubleTime ();
261
262                 Host_Frame (framenewtime - frameoldtime);
263
264                 frameoldtime = framenewtime;
265         }
266         return 0;
267 }