***map loader generates portals for the map*** (can you tell this is a big deal? :)
[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 #if NOTUSED
34 cvar_t  sys_linerefresh = {"sys_linerefresh","0"};// set for entity display
35 #endif
36
37 extern cvar_t   timestamps;
38 extern cvar_t   timeformat;
39
40 /* The translation table between the graphical font and plain ASCII  --KB */
41 static char qfont_table[256] = {
42         '\0', '#',  '#',  '#',  '#',  '.',  '#',  '#',
43         '#',  9,    10,   '#',  ' ',  13,   '.',  '.',
44         '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
45         '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
46         ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
47         '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
48         '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
49         '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
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         '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
55         'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
56         'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
57         'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<',
58
59         '<',  '=',  '>',  '#',  '#',  '.',  '#',  '#',
60         '#',  '#',  ' ',  '#',  ' ',  '>',  '.',  '.',
61         '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
62         '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
63         ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
64         '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
65         '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
66         '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
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         '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
72         'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o', 
73         'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
74         'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<'
75 };
76
77 // =======================================================================
78 // General routines
79 // =======================================================================
80
81 void Sys_DebugNumber(int y, int val)
82 {
83 }
84
85 /*
86 void Sys_Printf (char *fmt, ...)
87 {
88         va_list         argptr;
89         char            text[1024];
90         
91         va_start (argptr,fmt);
92         vsprintf (text,fmt,argptr);
93         va_end (argptr);
94         fprintf(stderr, "%s", text);
95         
96         Con_Print (text);
97 }
98
99 void Sys_Printf (char *fmt, ...)
100 {
101
102     va_list     argptr;
103     char        text[1024], *t_p;
104     int         l, r;
105
106         if (nostdout)
107                 return;
108
109     va_start (argptr,fmt);
110     vsprintf (text,fmt,argptr);
111     va_end (argptr);
112
113     l = strlen(text);
114     t_p = text;
115
116 // make sure everything goes through, even though we are non-blocking
117     while (l)
118     {
119         r = write (1, text, l);
120         if (r != l)
121             sleep (0);
122         if (r > 0)
123         {
124             t_p += r;
125             l -= r;
126         }
127     }
128
129 }
130 */
131
132 #define MAX_PRINT_MSG   4096
133 void Sys_Printf (char *fmt, ...)
134 {
135         va_list         argptr;
136         char            start[MAX_PRINT_MSG];   // String we started with
137         char            stamp[MAX_PRINT_MSG];   // Time stamp
138         char            final[MAX_PRINT_MSG];   // String we print
139
140         time_t          mytime = 0;
141         struct tm       *local = NULL;
142
143         unsigned char           *p;
144
145         va_start (argptr, fmt);
146         vsnprintf (start, sizeof(start), fmt, argptr);
147         va_end (argptr);
148
149         if (nostdout)
150                 return;
151
152         if (timestamps.value) {
153                 mytime = time (NULL);
154                 local = localtime (&mytime);
155                 strftime (stamp, sizeof (stamp), timeformat.string, local);
156                 
157                 snprintf (final, sizeof (final), "%s%s", stamp, start);
158         } else {
159                 snprintf (final, sizeof (final), "%s", start);
160         }
161
162         for (p = (unsigned char *) final; *p; p++) {
163                 putc (qfont_table[*p], stdout);
164         }
165         fflush (stdout);
166 }
167
168 #if 0
169 static char end1[] =
170 "\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
171 egistered trademark licensed to        \x1b[22;1H                 Nothing Interactive, Inc. All rights reserved.                 \x1b[40m\x1b[23;1H\x1b[0m";
172 static char end2[] =
173 "\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
174 IN logo is a registered trademark licensed        \x1b[22;1H             to Nothing Interactive, Inc. All rights reserved.                  \x1b[23;1H\x1b[40m\x1b[0m";
175
176 #endif
177 void Sys_Quit (void)
178 {
179         Host_Shutdown();
180     fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
181 #if 0
182         if (registered.value)
183                 printf("%s", end2);
184         else
185                 printf("%s", end1);
186 #endif
187         fflush(stdout);
188         exit(0);
189 }
190
191 void Sys_Init(void)
192 {
193 }
194
195 void Sys_Error (char *error, ...)
196
197     va_list     argptr;
198     char        string[1024];
199
200 // change stdin to non blocking
201     fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
202     
203     va_start (argptr,error);
204     vsprintf (string,error,argptr);
205     va_end (argptr);
206         fprintf(stderr, "Error: %s\n", string);
207
208         Host_Shutdown ();
209         exit (1);
210
211
212
213 void Sys_Warn (char *warning, ...)
214
215     va_list     argptr;
216     char        string[1024];
217     
218     va_start (argptr,warning);
219     vsprintf (string,warning,argptr);
220     va_end (argptr);
221         fprintf(stderr, "Warning: %s", string);
222
223
224 /*
225 ============
226 Sys_FileTime
227
228 returns -1 if not present
229 ============
230 */
231 int     Sys_FileTime (char *path)
232 {
233         struct  stat    buf;
234         
235         if (stat (path,&buf) == -1)
236                 return -1;
237         
238         return buf.st_mtime;
239 }
240
241
242 void Sys_mkdir (char *path)
243 {
244     mkdir (path, 0777);
245 }
246
247 int Sys_FileOpenRead (char *path, int *handle)
248 {
249         int     h;
250         struct stat     fileinfo;
251     
252         
253         h = open (path, O_RDONLY, 0666);
254         *handle = h;
255         if (h == -1)
256                 return -1;
257         
258         if (fstat (h,&fileinfo) == -1)
259                 Sys_Error ("Error fstating %s", path);
260
261         return fileinfo.st_size;
262 }
263
264 int Sys_FileOpenWrite (char *path)
265 {
266         int     handle;
267
268         umask (0);
269         
270         handle = open(path,O_RDWR | O_CREAT | O_TRUNC
271         , 0666);
272
273         if (handle == -1)
274                 Sys_Error ("Error opening %s: %s", path,strerror(errno));
275
276         return handle;
277 }
278
279 int Sys_FileWrite (int handle, void *src, int count)
280 {
281         return write (handle, src, count);
282 }
283
284 void Sys_FileClose (int handle)
285 {
286         close (handle);
287 }
288
289 void Sys_FileSeek (int handle, int position)
290 {
291         lseek (handle, position, SEEK_SET);
292 }
293
294 int Sys_FileRead (int handle, void *dest, int count)
295 {
296     return read (handle, dest, count);
297 }
298
299 void Sys_DebugLog(char *file, char *fmt, ...)
300 {
301     va_list argptr; 
302     static char data[1024];
303     int fd;
304     
305     va_start(argptr, fmt);
306     vsprintf(data, fmt, argptr);
307     va_end(argptr);
308 //    fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666);
309     fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
310     write(fd, data, strlen(data));
311     close(fd);
312 }
313
314 #if NOTUSED
315 void Sys_EditFile(char *filename)
316 {
317
318         char cmd[256];
319         char *term;
320         char *editor;
321
322         term = getenv("TERM");
323         if (term && !strcmp(term, "xterm"))
324         {
325                 editor = getenv("VISUAL");
326                 if (!editor)
327                         editor = getenv("EDITOR");
328                 if (!editor)
329                         editor = getenv("EDIT");
330                 if (!editor)
331                         editor = "vi";
332                 sprintf(cmd, "xterm -e %s %s", editor, filename);
333                 system(cmd);
334         }
335 }
336 #endif
337
338 double Sys_FloatTime (void)
339 {
340     struct timeval tp;
341     struct timezone tzp; 
342     static int      secbase; 
343     
344     gettimeofday(&tp, &tzp);  
345
346     if (!secbase)
347     {
348         secbase = tp.tv_sec;
349         return tp.tv_usec/1000000.0;
350     }
351
352     return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
353 }
354
355 // =======================================================================
356 // Sleeps for microseconds
357 // =======================================================================
358
359 static volatile int oktogo;
360
361 void alarm_handler(int x)
362 {
363         oktogo=1;
364 }
365
366 #if NOTUSED
367 void Sys_LineRefresh(void)
368 {
369 }
370 #endif
371
372 void floating_point_exception_handler(int whatever)
373 {
374 //      Sys_Warn("floating point exception\n");
375         signal(SIGFPE, floating_point_exception_handler);
376 }
377
378 char *Sys_ConsoleInput(void)
379 {
380     static char text[256];
381     int     len;
382         fd_set  fdset;
383     struct timeval timeout;
384
385         if (cls.state == ca_dedicated) {
386                 FD_ZERO(&fdset);
387                 FD_SET(0, &fdset); // stdin
388                 timeout.tv_sec = 0;
389                 timeout.tv_usec = 0;
390                 if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
391                         return NULL;
392
393                 len = read (0, text, sizeof(text));
394                 if (len < 1)
395                         return NULL;
396                 text[len-1] = 0;    // rip off the /n and terminate
397
398                 return text;
399         }
400         return NULL;
401 }
402
403 void Sys_Sleep(void)
404 {
405         usleep(1);
406 }
407
408 int main (int c, char **v)
409 {
410
411         double          time, oldtime, newtime;
412
413 //      static char cwd[1024];
414
415 //      signal(SIGFPE, floating_point_exception_handler);
416         signal(SIGFPE, SIG_IGN);
417
418         memset(&host_parms, 0, sizeof(host_parms));
419
420         COM_InitArgv(c, v);
421         host_parms.argc = com_argc;
422         host_parms.argv = com_argv;
423
424         host_parms.memsize = DEFAULTMEM * 1024*1024;
425
426         host_parms.basedir = basedir;
427
428         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
429
430         Host_Init();
431
432         Sys_Init();
433
434         if (COM_CheckParm("-nostdout"))
435                 nostdout = 1;
436         else
437         {
438                 fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
439                 printf ("Linux DarkPlaces -- Version %0.3f (build %i)\n", VERSION, buildnumber);
440         }
441
442         oldtime = Sys_FloatTime () - 0.1;
443         while (1)
444         {
445                 // find time spent rendering last frame
446                 newtime = Sys_FloatTime ();
447                 time = newtime - oldtime;
448
449                 if (cls.state == ca_dedicated)
450                 {
451                         if (time < sys_ticrate.value)
452                         {
453                                 usleep(1);
454                                 continue;       // not time to run a server only tic yet
455                         }
456                         time = sys_ticrate.value;
457                 }
458
459                 if (time > sys_ticrate.value*2)
460                         oldtime = newtime;
461                 else
462                         oldtime += time;
463
464                 Host_Frame (time);
465
466 #if NOTUSED
467                 // graphic debugging aids
468                 if (sys_linerefresh.value)
469                         Sys_LineRefresh ();
470 #endif
471         }
472         return 0;
473 }
474
475
476 #if NOTUSED
477 /*
478 ================
479 Sys_MakeCodeWriteable
480 ================
481 */
482 void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
483 {
484
485         int r;
486         unsigned long addr;
487         int psize = getpagesize();
488
489         addr = (startaddr & ~(psize-1)) - psize;
490
491 //      fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
492 //                      addr, startaddr+length, length);
493
494         r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
495
496         if (r < 0)
497                 Sys_Error("Protection change failed\n");
498
499 }
500 #endif
501