only warn about time stepping backwards if it's more than 10ms
[divverent/darkplaces.git] / sys_linux.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9
10 #include <signal.h>
11 #include <limits.h>
12 #include <sys/ipc.h>
13 #include <sys/shm.h>
14 #include <sys/time.h>
15 #include <sys/wait.h>
16 #include <sys/mman.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <errno.h>
20 #include <time.h>
21
22 #include "quakedef.h"
23
24 char *basedir = ".";
25 #if CACHEENABLE
26 char *cachedir = "/tmp";
27 #endif
28
29 // =======================================================================
30 // General routines
31 // =======================================================================
32
33 void Sys_DebugNumber(int y, int val)
34 {
35 }
36
37 void Sys_Quit (void)
38 {
39         Host_Shutdown();
40         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
41         fflush(stdout);
42         exit(0);
43 }
44
45 void Sys_Error (char *error, ...)
46 {
47         va_list argptr;
48         char string[1024];
49
50 // change stdin to non blocking
51         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
52
53         va_start (argptr,error);
54         vsprintf (string,error,argptr);
55         va_end (argptr);
56         fprintf(stderr, "Error: %s\n", string);
57
58         Host_Shutdown ();
59         exit (1);
60
61 }
62
63 void Sys_Warn (char *warning, ...)
64 {
65         va_list argptr;
66         char string[1024];
67
68         va_start (argptr,warning);
69         vsprintf (string,warning,argptr);
70         va_end (argptr);
71         fprintf(stderr, "Warning: %s", string);
72 }
73
74 /*
75 ============
76 Sys_FileTime
77
78 returns -1 if not present
79 ============
80 */
81 int Sys_FileTime (char *path)
82 {
83         struct stat buf;
84
85         if (stat (path,&buf) == -1)
86                 return -1;
87
88         return buf.st_mtime;
89 }
90
91
92 void Sys_mkdir (char *path)
93 {
94         mkdir (path, 0777);
95 }
96
97 int Sys_FileOpenRead (char *path, int *handle)
98 {
99         int h;
100         struct stat fileinfo;
101
102         h = open (path, O_RDONLY, 0666);
103         *handle = h;
104         if (h == -1)
105                 return -1;
106
107         if (fstat (h,&fileinfo) == -1)
108                 Sys_Error ("Error fstating %s", path);
109
110         return fileinfo.st_size;
111 }
112
113 int Sys_FileOpenWrite (char *path)
114 {
115         int handle;
116
117         umask (0);
118
119         handle = open(path,O_RDWR | O_CREAT | O_TRUNC, 0666);
120
121         if (handle == -1)
122         {
123                 Con_Printf("Sys_FileOpenWrite: Error opening %s: %s", path, strerror(errno));
124                 return 0;
125         }
126
127         return handle;
128 }
129
130 int Sys_FileWrite (int handle, void *src, int count)
131 {
132         return write (handle, src, count);
133 }
134
135 void Sys_FileClose (int handle)
136 {
137         close (handle);
138 }
139
140 void Sys_FileSeek (int handle, int position)
141 {
142         lseek (handle, position, SEEK_SET);
143 }
144
145 int Sys_FileRead (int handle, void *dest, int count)
146 {
147         return read (handle, dest, count);
148 }
149
150 void Sys_DebugLog(char *file, char *fmt, ...)
151 {
152         va_list argptr;
153         static char data[1024];
154         int fd;
155
156         va_start(argptr, fmt);
157         vsprintf(data, fmt, argptr);
158         va_end(argptr);
159         fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
160         write(fd, data, strlen(data));
161         close(fd);
162 }
163
164 double Sys_DoubleTime (void)
165 {
166         static int first = true;
167         static double oldtime = 0.0, curtime = 0.0;
168         double newtime;
169         struct timeval tp;
170
171         gettimeofday(&tp, NULL);
172
173         newtime = (double) tp.tv_sec + tp.tv_usec / 1000000.0;
174
175         if (first)
176         {
177                 first = false;
178                 oldtime = newtime;
179         }
180
181         if (newtime < oldtime)
182         {
183                 // warn if it's significant
184                 if (newtime - oldtime < -0.01)
185                         Con_Printf("Sys_DoubleTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
186         }
187         else
188                 curtime += newtime - oldtime;
189         oldtime = newtime;
190
191         return curtime;
192 }
193
194 // =======================================================================
195 // Sleeps for microseconds
196 // =======================================================================
197
198 static volatile int oktogo;
199
200 void alarm_handler(int x)
201 {
202         oktogo=1;
203 }
204
205 void floating_point_exception_handler(int whatever)
206 {
207         signal(SIGFPE, floating_point_exception_handler);
208 }
209
210 char *Sys_ConsoleInput(void)
211 {
212         static char text[256];
213         int len;
214         fd_set fdset;
215         struct timeval timeout;
216
217         if (cls.state == ca_dedicated)
218         {
219                 FD_ZERO(&fdset);
220                 FD_SET(0, &fdset); // stdin
221                 timeout.tv_sec = 0;
222                 timeout.tv_usec = 0;
223                 if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
224                         return NULL;
225
226                 len = read (0, text, sizeof(text));
227                 if (len < 1)
228                         return NULL;
229                 text[len-1] = 0;    // rip off the /n and terminate
230
231                 return text;
232         }
233         return NULL;
234 }
235
236 void Sys_Sleep(void)
237 {
238         usleep(1);
239 }
240
241 int main (int c, char **v)
242 {
243         double frameoldtime, framenewtime;
244
245         signal(SIGFPE, SIG_IGN);
246
247         memset(&host_parms, 0, sizeof(host_parms));
248
249         COM_InitArgv(c, v);
250         host_parms.argc = com_argc;
251         host_parms.argv = com_argv;
252
253         host_parms.basedir = basedir;
254
255         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
256
257         Sys_Shared_EarlyInit();
258
259         Host_Init();
260
261         Sys_Shared_LateInit();
262
263         frameoldtime = Sys_DoubleTime () - 0.1;
264         while (1)
265         {
266                 // find time spent rendering last frame
267                 framenewtime = Sys_DoubleTime ();
268
269                 Host_Frame (framenewtime - frameoldtime);
270
271                 frameoldtime = framenewtime;
272         }
273         return 0;
274 }