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