Fixed major bug in time wrap code, would have not advanced clock at all after wrap...
[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                 curtime += newtime - oldtime;
186         oldtime = newtime;
187
188         return curtime;
189 }
190
191 // =======================================================================
192 // Sleeps for microseconds
193 // =======================================================================
194
195 static volatile int oktogo;
196
197 void alarm_handler(int x)
198 {
199         oktogo=1;
200 }
201
202 void floating_point_exception_handler(int whatever)
203 {
204         signal(SIGFPE, floating_point_exception_handler);
205 }
206
207 char *Sys_ConsoleInput(void)
208 {
209         static char text[256];
210         int len;
211         fd_set fdset;
212         struct timeval timeout;
213
214         if (cls.state == ca_dedicated)
215         {
216                 FD_ZERO(&fdset);
217                 FD_SET(0, &fdset); // stdin
218                 timeout.tv_sec = 0;
219                 timeout.tv_usec = 0;
220                 if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
221                         return NULL;
222
223                 len = read (0, text, sizeof(text));
224                 if (len < 1)
225                         return NULL;
226                 text[len-1] = 0;    // rip off the /n and terminate
227
228                 return text;
229         }
230         return NULL;
231 }
232
233 void Sys_Sleep(void)
234 {
235         usleep(1);
236 }
237
238 int main (int c, char **v)
239 {
240         double oldtime, newtime;
241
242         signal(SIGFPE, SIG_IGN);
243
244         memset(&host_parms, 0, sizeof(host_parms));
245
246         COM_InitArgv(c, v);
247         host_parms.argc = com_argc;
248         host_parms.argv = com_argv;
249
250         host_parms.basedir = basedir;
251
252         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
253
254         Sys_Shared_EarlyInit();
255
256         Host_Init();
257
258         Sys_Shared_LateInit();
259
260         oldtime = Sys_DoubleTime () - 0.1;
261         while (1)
262         {
263                 // find time spent rendering last frame
264                 newtime = Sys_DoubleTime ();
265
266                 Host_Frame (newtime - oldtime);
267
268                 oldtime = newtime;
269         }
270         return 0;
271 }