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