Major update, been neglecting CVS for some time...
[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 qboolean                        isDedicated;
25
26 int nostdout = 0;
27
28 char *basedir = ".";
29 #if CACHEENABLE
30 char *cachedir = "/tmp";
31 #endif
32
33 extern cvar_t   timestamps;
34 extern cvar_t   timeformat;
35
36 /* The translation table between the graphical font and plain ASCII  --KB */
37 static char qfont_table[256] = {
38         '\0', '#',  '#',  '#',  '#',  '.',  '#',  '#',
39         '#',  9,    10,   '#',  ' ',  13,   '.',  '.',
40         '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
41         '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
42         ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
43         '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
44         '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
45         '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
46         '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
47         'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
48         'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
49         'X',  'Y',  'Z',  '[',  '\\', ']',  '^',  '_',
50         '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
51         'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
52         'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
53         'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<',
54
55         '<',  '=',  '>',  '#',  '#',  '.',  '#',  '#',
56         '#',  '#',  ' ',  '#',  ' ',  '>',  '.',  '.',
57         '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
58         '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
59         ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
60         '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
61         '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
62         '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
63         '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
64         'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
65         'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
66         'X',  'Y',  'Z',  '[',  '\\', ']',  '^',  '_',
67         '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
68         'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o', 
69         'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
70         'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<'
71 };
72
73 // =======================================================================
74 // General routines
75 // =======================================================================
76
77 void Sys_DebugNumber(int y, int val)
78 {
79 }
80
81 /*
82 void Sys_Printf (char *fmt, ...)
83 {
84         va_list         argptr;
85         char            text[1024];
86         
87         va_start (argptr,fmt);
88         vsprintf (text,fmt,argptr);
89         va_end (argptr);
90         Qprintf(stderr, "%s", text);
91         
92         Con_Print (text);
93 }
94
95 void Sys_Printf (char *fmt, ...)
96 {
97
98     va_list     argptr;
99     char        text[1024], *t_p;
100     int         l, r;
101
102         if (nostdout)
103                 return;
104
105     va_start (argptr,fmt);
106     vsprintf (text,fmt,argptr);
107     va_end (argptr);
108
109     l = strlen(text);
110     t_p = text;
111
112 // make sure everything goes through, even though we are non-blocking
113     while (l)
114     {
115         r = write (1, text, l);
116         if (r != l)
117             sleep (0);
118         if (r > 0)
119         {
120             t_p += r;
121             l -= r;
122         }
123     }
124
125 }
126 */
127
128 #define MAX_PRINT_MSG   4096
129 void Sys_Printf (char *fmt, ...)
130 {
131         va_list         argptr;
132         char            start[MAX_PRINT_MSG];   // String we started with
133         char            stamp[MAX_PRINT_MSG];   // Time stamp
134         char            final[MAX_PRINT_MSG];   // String we print
135
136         time_t          mytime = 0;
137         struct tm       *local = NULL;
138
139         unsigned char           *p;
140
141         va_start (argptr, fmt);
142         vsnprintf (start, sizeof(start), fmt, argptr);
143         va_end (argptr);
144
145         if (nostdout)
146                 return;
147
148         if (timestamps.value) {
149                 mytime = time (NULL);
150                 local = localtime (&mytime);
151                 strftime (stamp, sizeof (stamp), timeformat.string, local);
152                 
153                 snprintf (final, sizeof (final), "%s%s", stamp, start);
154         } else {
155                 snprintf (final, sizeof (final), "%s", start);
156         }
157
158         for (p = (unsigned char *) final; *p; p++) {
159                 putc (qfont_table[*p], stdout);
160         }
161         fflush (stdout);
162 }
163
164 #if 0
165 static char end1[] =
166 "\x1b[?7h\x1b[40m\x1b[2J\x1b[0;1;41m\x1b[1;1H                QUAKE: The Doomed Dimension \x1b[33mby \x1b[44mid\x1b[41m Software                      \x1b[2;1H  ----------------------------------------------------------------------------  \x1b[3;1H           CALL 1-800-IDGAMES TO ORDER OR FOR TECHNICAL SUPPORT                 \x1b[4;1H             PRICE: $45.00 (PRICES MAY VARY OUTSIDE THE US.)                    \x1b[5;1H                                                                                \x1b[6;1H  \x1b[37mYes! You only have one fourth of this incredible epic. That is because most   \x1b[7;1H   of you have paid us nothing or at most, very little. You could steal the     \x1b[8;1H   game from a friend. But we both know you'll be punished by God if you do.    \x1b[9;1H        \x1b[33mWHY RISK ETERNAL DAMNATION? CALL 1-800-IDGAMES AND BUY NOW!             \x1b[10;1H             \x1b[37mRemember, we love you almost as much as He does.                   \x1b[11;1H                                                                                \x1b[12;1H            \x1b[33mProgramming: \x1b[37mJohn Carmack, Michael Abrash, John Cash                \x1b[13;1H       \x1b[33mDesign: \x1b[37mJohn Romero, Sandy Petersen, American McGee, Tim Willits         \x1b[14;1H                     \x1b[33mArt: \x1b[37mAdrian Carmack, Kevin Cloud                           \x1b[15;1H               \x1b[33mBiz: \x1b[37mJay Wilbur, Mike Wilson, Donna Jackson                      \x1b[16;1H            \x1b[33mProjects: \x1b[37mShawn Green   \x1b[33mSupport: \x1b[37mBarrett Alexander                  \x1b[17;1H              \x1b[33mSound Effects: \x1b[37mTrent Reznor and Nine Inch Nails                   \x1b[18;1H  For other information or details on ordering outside the US, check out the    \x1b[19;1H     files accompanying QUAKE or our website at http://www.idsoftware.com.      \x1b[20;1H    \x1b[0;41mQuake is a trademark of Id Software, inc., (c)1996 Id Software, inc.        \x1b[21;1H     All rights reserved. NIN logo is a r
167 egistered trademark licensed to        \x1b[22;1H                 Nothing Interactive, Inc. All rights reserved.                 \x1b[40m\x1b[23;1H\x1b[0m";
168 static char end2[] =
169 "\x1b[?7h\x1b[40m\x1b[2J\x1b[0;1;41m\x1b[1;1H        QUAKE \x1b[33mby \x1b[44mid\x1b[41m Software                                                    \x1b[2;1H -----------------------------------------------------------------------------  \x1b[3;1H        \x1b[37mWhy did you quit from the registered version of QUAKE? Did the          \x1b[4;1H        scary monsters frighten you? Or did Mr. Sandman tug at your             \x1b[5;1H        little lids? No matter! What is important is you love our               \x1b[6;1H        game, and gave us your money. Congratulations, you are probably         \x1b[7;1H        not a thief.                                                            \x1b[8;1H                                                           Thank You.           \x1b[9;1H        \x1b[33;44mid\x1b[41m Software is:                                                         \x1b[10;1H        PROGRAMMING: \x1b[37mJohn Carmack, Michael Abrash, John Cash                    \x1b[11;1H        \x1b[33mDESIGN: \x1b[37mJohn Romero, Sandy Petersen, American McGee, Tim Willits        \x1b[12;1H        \x1b[33mART: \x1b[37mAdrian Carmack, Kevin Cloud                                        \x1b[13;1H        \x1b[33mBIZ: \x1b[37mJay Wilbur, Mike Wilson     \x1b[33mPROJECTS MAN: \x1b[37mShawn Green              \x1b[14;1H        \x1b[33mBIZ ASSIST: \x1b[37mDonna Jackson        \x1b[33mSUPPORT: \x1b[37mBarrett Alexander             \x1b[15;1H        \x1b[33mSOUND EFFECTS AND MUSIC: \x1b[37mTrent Reznor and Nine Inch Nails               \x1b[16;1H                                                                                \x1b[17;1H        If you need help running QUAKE refer to the text files in the           \x1b[18;1H        QUAKE directory, or our website at http://www.idsoftware.com.           \x1b[19;1H        If all else fails, call our technical support at 1-800-IDGAMES.         \x1b[20;1H      \x1b[0;41mQuake is a trademark of Id Software, inc., (c)1996 Id Software, inc.      \x1b[21;1H        All rights reserved. N
170 IN logo is a registered trademark licensed        \x1b[22;1H             to Nothing Interactive, Inc. All rights reserved.                  \x1b[23;1H\x1b[40m\x1b[0m";
171
172 #endif
173 void Sys_Quit (void)
174 {
175         Host_Shutdown();
176     fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
177 #if 0
178         if (registered.value)
179                 printf("%s", end2);
180         else
181                 printf("%s", end1);
182 #endif
183         fflush(stdout);
184         exit(0);
185 }
186
187 void Sys_Error (char *error, ...)
188
189     va_list     argptr;
190     char        string[1024];
191
192 // change stdin to non blocking
193     fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
194     
195     va_start (argptr,error);
196     vsprintf (string,error,argptr);
197     va_end (argptr);
198         fprintf(stderr, "Error: %s\n", string);
199
200         Host_Shutdown ();
201         exit (1);
202
203
204
205 void Sys_Warn (char *warning, ...)
206
207     va_list     argptr;
208     char        string[1024];
209     
210     va_start (argptr,warning);
211     vsprintf (string,warning,argptr);
212     va_end (argptr);
213         fprintf(stderr, "Warning: %s", string);
214
215
216 /*
217 ============
218 Sys_FileTime
219
220 returns -1 if not present
221 ============
222 */
223 int     Sys_FileTime (char *path)
224 {
225         struct  stat    buf;
226         
227         if (stat (path,&buf) == -1)
228                 return -1;
229         
230         return buf.st_mtime;
231 }
232
233
234 void Sys_mkdir (char *path)
235 {
236     mkdir (path, 0777);
237 }
238
239 int Sys_FileOpenRead (char *path, int *handle)
240 {
241         int     h;
242         struct stat     fileinfo;
243     
244         
245         h = open (path, O_RDONLY, 0666);
246         *handle = h;
247         if (h == -1)
248                 return -1;
249         
250         if (fstat (h,&fileinfo) == -1)
251                 Sys_Error ("Error fstating %s", path);
252
253         return fileinfo.st_size;
254 }
255
256 int Sys_FileOpenWrite (char *path)
257 {
258         int     handle;
259
260         umask (0);
261         
262         handle = open(path,O_RDWR | O_CREAT | O_TRUNC, 0666);
263
264         if (handle == -1)
265         {
266                 Con_Printf("Sys_FileOpenWrite: Error opening %s: %s", path, strerror(errno));
267                 return 0;
268         }
269
270         return handle;
271 }
272
273 int Sys_FileWrite (int handle, void *src, int count)
274 {
275         return write (handle, src, count);
276 }
277
278 void Sys_FileClose (int handle)
279 {
280         close (handle);
281 }
282
283 void Sys_FileSeek (int handle, int position)
284 {
285         lseek (handle, position, SEEK_SET);
286 }
287
288 int Sys_FileRead (int handle, void *dest, int count)
289 {
290     return read (handle, dest, count);
291 }
292
293 void Sys_DebugLog(char *file, char *fmt, ...)
294 {
295     va_list argptr; 
296     static char data[1024];
297     int fd;
298     
299     va_start(argptr, fmt);
300     vsprintf(data, fmt, argptr);
301     va_end(argptr);
302 //    fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666);
303     fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
304     write(fd, data, strlen(data));
305     close(fd);
306 }
307
308 double Sys_DoubleTime (void)
309 {
310         static int first = true;
311         static double oldtime = 0.0, basetime = 0.0;
312         double newtime;
313         struct timeval tp;
314         struct timezone tzp; 
315
316         gettimeofday(&tp, &tzp);
317
318         newtime = (double) ((unsigned long) tp.tv_sec) + tp.tv_usec/1000000.0 - basetime;
319
320         if (first)
321         {
322                 first = false;
323                 basetime = newtime;
324                 newtime = 0.0;
325         }
326
327         if (newtime < oldtime)
328                 Sys_Error("Sys_DoubleTime: time running backwards??\n");
329
330         oldtime = newtime;
331
332         return newtime;
333 }
334
335 // =======================================================================
336 // Sleeps for microseconds
337 // =======================================================================
338
339 static volatile int oktogo;
340
341 void alarm_handler(int x)
342 {
343         oktogo=1;
344 }
345
346 void floating_point_exception_handler(int whatever)
347 {
348 //      Sys_Warn("floating point exception\n");
349         signal(SIGFPE, floating_point_exception_handler);
350 }
351
352 char *Sys_ConsoleInput(void)
353 {
354     static char text[256];
355     int     len;
356         fd_set  fdset;
357     struct timeval timeout;
358
359         if (cls.state == ca_dedicated) {
360                 FD_ZERO(&fdset);
361                 FD_SET(0, &fdset); // stdin
362                 timeout.tv_sec = 0;
363                 timeout.tv_usec = 0;
364                 if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
365                         return NULL;
366
367                 len = read (0, text, sizeof(text));
368                 if (len < 1)
369                         return NULL;
370                 text[len-1] = 0;    // rip off the /n and terminate
371
372                 return text;
373         }
374         return NULL;
375 }
376
377 void Sys_Sleep(void)
378 {
379         usleep(1);
380 }
381
382 int main (int c, char **v)
383 {
384
385         double oldtime, newtime;
386
387 //      static char cwd[1024];
388
389 //      signal(SIGFPE, floating_point_exception_handler);
390         signal(SIGFPE, SIG_IGN);
391
392         memset(&host_parms, 0, sizeof(host_parms));
393
394         COM_InitArgv(c, v);
395         host_parms.argc = com_argc;
396         host_parms.argv = com_argv;
397
398         host_parms.memsize = DEFAULTMEM * 1024*1024;
399
400         host_parms.basedir = basedir;
401
402         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
403
404         Host_Init();
405
406         if (COM_CheckParm("-nostdout"))
407                 nostdout = 1;
408         else
409         {
410                 fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
411                 printf ("Linux DarkPlaces -- Version %0.3f (build %i)\n", VERSION, buildnumber);
412         }
413
414         oldtime = Sys_DoubleTime () - 0.1;
415         while (1)
416         {
417                 // find time spent rendering last frame
418                 newtime = Sys_DoubleTime ();
419
420                 Host_Frame (newtime - oldtime);
421
422                 oldtime = newtime;
423         }
424         return 0;
425 }