timer now simply returns the same time twice if the OS value wraps, and posts a warni...
[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         struct timezone tzp;
171
172         gettimeofday(&tp, &tzp);
173
174         newtime = (double) ((unsigned long) tp.tv_sec) + tp.tv_usec/1000000.0;
175
176         if (first)
177         {
178                 first = false;
179                 oldtime = newtime;
180         }
181
182         if (newtime < oldtime)
183                 Con_Printf("Sys_DoubleTime: time running backwards??\n");
184         else
185         {
186                 curtime += newtime - oldtime;
187                 oldtime = newtime;
188         }
189
190         return curtime;
191 }
192
193 // =======================================================================
194 // Sleeps for microseconds
195 // =======================================================================
196
197 static volatile int oktogo;
198
199 void alarm_handler(int x)
200 {
201         oktogo=1;
202 }
203
204 void floating_point_exception_handler(int whatever)
205 {
206         signal(SIGFPE, floating_point_exception_handler);
207 }
208
209 char *Sys_ConsoleInput(void)
210 {
211         static char text[256];
212         int len;
213         fd_set fdset;
214         struct timeval timeout;
215
216         if (cls.state == ca_dedicated)
217         {
218                 FD_ZERO(&fdset);
219                 FD_SET(0, &fdset); // stdin
220                 timeout.tv_sec = 0;
221                 timeout.tv_usec = 0;
222                 if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
223                         return NULL;
224
225                 len = read (0, text, sizeof(text));
226                 if (len < 1)
227                         return NULL;
228                 text[len-1] = 0;    // rip off the /n and terminate
229
230                 return text;
231         }
232         return NULL;
233 }
234
235 void Sys_Sleep(void)
236 {
237         usleep(1);
238 }
239
240 int main (int c, char **v)
241 {
242         double oldtime, newtime;
243
244         signal(SIGFPE, SIG_IGN);
245
246         memset(&host_parms, 0, sizeof(host_parms));
247
248         COM_InitArgv(c, v);
249         host_parms.argc = com_argc;
250         host_parms.argv = com_argv;
251
252         host_parms.basedir = basedir;
253
254         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
255
256         Sys_Shared_EarlyInit();
257
258         Host_Init();
259
260         Sys_Shared_LateInit();
261
262         oldtime = Sys_DoubleTime () - 0.1;
263         while (1)
264         {
265                 // find time spent rendering last frame
266                 newtime = Sys_DoubleTime ();
267
268                 Host_Frame (newtime - oldtime);
269
270                 oldtime = newtime;
271         }
272         return 0;
273 }