Sys_Print added to handle the output of text to the terminal (since this varies from...
[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 void Sys_Print(const char *text)
90 {
91         printf("%s", text);
92 }
93
94 double Sys_DoubleTime (void)
95 {
96         static int first = true;
97         static double oldtime = 0.0, curtime = 0.0;
98         double newtime;
99 #ifdef WIN32
100         // LordHavoc: note to people modifying this code, DWORD is specifically defined as an unsigned 32bit number, therefore the 65536.0 * 65536.0 is fine.
101         if (sys_usetimegettime.integer)
102         {
103                 static int firsttimegettime = true;
104                 // timeGetTime
105                 // platform:
106                 // Windows 95/98/ME/NT/2000/XP
107                 // features:
108                 // reasonable accuracy (millisecond)
109                 // issues:
110                 // wraps around every 47 days or so (but this is non-fatal to us, odd times are rejected, only causes a one frame stutter)
111
112                 // make sure the timer is high precision, otherwise different versions of windows have varying accuracy
113                 if (firsttimegettime)
114                 {
115                         timeBeginPeriod (1);
116                         firsttimegettime = false;
117                 }
118
119                 newtime = (double) timeGetTime () / 1000.0;
120         }
121         else
122         {
123                 // QueryPerformanceCounter
124                 // platform:
125                 // Windows 95/98/ME/NT/2000/XP
126                 // features:
127                 // very accurate (CPU cycles)
128                 // known issues:
129                 // does not necessarily match realtime too well (tends to get faster and faster in win98)
130                 // wraps around occasionally on some platforms (depends on CPU speed and probably other unknown factors)
131                 double timescale;
132                 LARGE_INTEGER PerformanceFreq;
133                 LARGE_INTEGER PerformanceCount;
134
135                 if (!QueryPerformanceFrequency (&PerformanceFreq))
136                         Sys_Error ("No hardware timer available");
137                 QueryPerformanceCounter (&PerformanceCount);
138
139                 #ifdef __BORLANDC__
140                 timescale = 1.0 / ((double) PerformanceFreq.u.LowPart + (double) PerformanceFreq.u.HighPart * 65536.0 * 65536.0);
141                 newtime = ((double) PerformanceCount.u.LowPart + (double) PerformanceCount.u.HighPart * 65536.0 * 65536.0) * timescale;
142                 #else
143                 timescale = 1.0 / ((double) PerformanceFreq.LowPart + (double) PerformanceFreq.HighPart * 65536.0 * 65536.0);
144                 newtime = ((double) PerformanceCount.LowPart + (double) PerformanceCount.HighPart * 65536.0 * 65536.0) * timescale;
145                 #endif
146         }
147 #else
148         struct timeval tp;
149         gettimeofday(&tp, NULL);
150         newtime = (double) tp.tv_sec + tp.tv_usec / 1000000.0;
151 #endif
152
153         if (first)
154         {
155                 first = false;
156                 oldtime = newtime;
157         }
158
159         if (newtime < oldtime)
160         {
161                 // warn if it's significant
162                 if (newtime - oldtime < -0.01)
163                         Con_Printf("Sys_DoubleTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
164         }
165         else
166                 curtime += newtime - oldtime;
167         oldtime = newtime;
168
169         return curtime;
170 }
171
172 char *Sys_ConsoleInput(void)
173 {
174         if (cls.state == ca_dedicated)
175         {
176                 static char text[256];
177                 int len;
178 #ifdef WIN32
179                 int c;
180
181                 // read a line out
182                 while (_kbhit ())
183                 {
184                         c = _getch ();
185                         putch (c);
186                         if (c == '\r')
187                         {
188                                 text[len] = 0;
189                                 putch ('\n');
190                                 len = 0;
191                                 return text;
192                         }
193                         if (c == 8)
194                         {
195                                 if (len)
196                                 {
197                                         putch (' ');
198                                         putch (c);
199                                         len--;
200                                         text[len] = 0;
201                                 }
202                                 continue;
203                         }
204                         text[len] = c;
205                         len++;
206                         text[len] = 0;
207                         if (len == sizeof (text))
208                                 len = 0;
209                 }
210 #else
211                 fd_set fdset;
212                 struct timeval timeout;
213                 FD_ZERO(&fdset);
214                 FD_SET(0, &fdset); // stdin
215                 timeout.tv_sec = 0;
216                 timeout.tv_usec = 0;
217                 if (select (1, &fdset, NULL, NULL, &timeout) != -1 && FD_ISSET(0, &fdset))
218                 {
219                         len = read (0, text, sizeof(text));
220                         if (len >= 1)
221                         {
222                                 // rip off the \n and terminate
223                                 text[len-1] = 0;
224                                 return text;
225                         }
226                 }
227 #endif
228         }
229         return NULL;
230 }
231
232 void Sys_Sleep(void)
233 {
234 #ifdef WIN32
235         Sleep (1);
236 #else
237         usleep(1);
238 #endif
239 }
240
241 int main (int argc, const char **argv)
242 {
243         double frameoldtime, framenewtime;
244
245         signal(SIGFPE, SIG_IGN);
246
247         com_argc = argc;
248         com_argv = argv;
249
250 #ifndef WIN32
251         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
252 #endif
253
254         Sys_Shared_EarlyInit();
255
256         Host_Init();
257
258         Sys_Shared_LateInit();
259
260         frameoldtime = Sys_DoubleTime () - 0.1;
261         while (1)
262         {
263                 // find time spent rendering last frame
264                 framenewtime = Sys_DoubleTime ();
265
266                 Host_Frame (framenewtime - frameoldtime);
267
268                 frameoldtime = framenewtime;
269         }
270         return 0;
271 }