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