1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19*/
20#include <unistd.h>
21#include <signal.h>
22#include <stdlib.h>
23#include <limits.h>
24#include <sys/time.h>
25#include <sys/types.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <stdarg.h>
29#include <stdio.h>
30#include <sys/ipc.h>
31#include <sys/shm.h>
32#include <sys/stat.h>
33#include <string.h>
34#include <ctype.h>
35#include <sys/wait.h>
36#include <sys/mman.h>
37#include <errno.h>
38
39#include "quakedef.h"
40
41int noconinput = 0;
42int nostdout = 0;
43
44char *basedir = ".";
45char *cachedir = "/tmp";
46
47cvar_t  sys_linerefresh = CVAR2("sys_linerefresh","0");// set for entity display
48
49// =======================================================================
50// General routines
51// =======================================================================
52
53void Sys_DebugNumber(int y, int val)
54{
55}
56
57/*
58void Sys_Printf (char *fmt, ...)
59{
60	va_list		argptr;
61	char		text[1024];
62
63	va_start (argptr,fmt);
64	vsprintf (text,fmt,argptr);
65	va_end (argptr);
66	fprintf(stderr, "%s", text);
67
68	Con_Print (text);
69}
70
71void Sys_Printf (char *fmt, ...)
72{
73
74    va_list     argptr;
75    char        text[1024], *t_p;
76    int         l, r;
77
78    if (nostdout)
79        return;
80
81    va_start (argptr,fmt);
82    vsprintf (text,fmt,argptr);
83    va_end (argptr);
84
85    l = strlen(text);
86    t_p = text;
87
88// make sure everything goes through, even though we are non-blocking
89    while (l)
90    {
91        r = write (1, text, l);
92        if (r != l)
93            sleep (0);
94        if (r > 0)
95        {
96            t_p += r;
97            l -= r;
98        }
99    }
100
101}
102*/
103
104void Sys_Printf (char *fmt, ...)
105{
106	va_list		argptr;
107	char		text[2048];
108	unsigned char		*p;
109
110	va_start (argptr,fmt);
111	vsprintf (text,fmt,argptr);
112	va_end (argptr);
113
114	if (strlen(text) > sizeof(text))
115		Sys_Error("memory overwrite in Sys_Printf");
116
117    if (nostdout)
118        return;
119
120	for (p = (unsigned char *)text; *p; p++)
121		if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
122			printf("[%02x]", *p);
123		else
124			putc(*p, stdout);
125}
126
127void Sys_Quit (void)
128{
129	Host_Shutdown();
130    fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
131	exit(0);
132}
133
134void Sys_Init(void)
135{
136#if id386
137	Sys_SetFPCW();
138#endif
139}
140
141void Sys_Error (char *error, ...)
142{
143    va_list     argptr;
144    char        string[1024];
145
146// change stdin to non blocking
147    fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
148
149    va_start (argptr,error);
150    vsprintf (string,error,argptr);
151    va_end (argptr);
152	fprintf(stderr, "Error: %s\n", string);
153
154	Host_Shutdown ();
155	exit (1);
156
157}
158
159void Sys_Warn (char *warning, ...)
160{
161    va_list     argptr;
162    char        string[1024];
163
164    va_start (argptr,warning);
165    vsprintf (string,warning,argptr);
166    va_end (argptr);
167	fprintf(stderr, "Warning: %s", string);
168}
169
170/*
171============
172Sys_FileTime
173
174returns -1 if not present
175============
176*/
177int	Sys_FileTime (char *path)
178{
179	struct	stat	buf;
180
181	if (stat (path,&buf) == -1)
182		return -1;
183
184	return buf.st_mtime;
185}
186
187
188void Sys_mkdir (char *path)
189{
190    mkdir (path, 0777);
191}
192
193int Sys_FileOpenRead (char *path, int *handle)
194{
195	int	h;
196	struct stat	fileinfo;
197
198
199	h = open (path, O_RDONLY, 0666);
200	*handle = h;
201	if (h == -1)
202		return -1;
203
204	if (fstat (h,&fileinfo) == -1)
205		Sys_Error ("Error fstating %s", path);
206
207	return fileinfo.st_size;
208}
209
210int Sys_FileOpenWrite (char *path)
211{
212	int     handle;
213
214	umask (0);
215
216	handle = open(path,O_RDWR | O_CREAT | O_TRUNC
217	, 0666);
218
219	if (handle == -1)
220		Sys_Error ("Error opening %s: %s", path,strerror(errno));
221
222	return handle;
223}
224
225int Sys_FileWrite (int handle, void *src, int count)
226{
227	return write (handle, src, count);
228}
229
230void Sys_FileClose (int handle)
231{
232	close (handle);
233}
234
235void Sys_FileSeek (int handle, int position)
236{
237	lseek (handle, position, SEEK_SET);
238}
239
240int Sys_FileRead (int handle, void *dest, int count)
241{
242    return read (handle, dest, count);
243}
244
245void Sys_DebugLog(char *file, char *fmt, ...)
246{
247    va_list argptr;
248    static char data[1024];
249    int fd;
250
251    va_start(argptr, fmt);
252    vsprintf(data, fmt, argptr);
253    va_end(argptr);
254//    fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666);
255    fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
256    write(fd, data, strlen(data));
257    close(fd);
258}
259
260void Sys_EditFile(char *filename)
261{
262
263	char cmd[256];
264	char *term;
265	char *editor;
266
267	term = getenv("TERM");
268	if (term && !strcmp(term, "xterm"))
269	{
270		editor = getenv("VISUAL");
271		if (!editor)
272			editor = getenv("EDITOR");
273		if (!editor)
274			editor = getenv("EDIT");
275		if (!editor)
276			editor = "vi";
277		sprintf(cmd, "xterm -e %s %s", editor, filename);
278		system(cmd);
279	}
280
281}
282
283double Sys_DoubleTime (void)
284{
285    struct timeval tp;
286    struct timezone tzp;
287    static int      secbase;
288
289    gettimeofday(&tp, &tzp);
290
291    if (!secbase)
292    {
293        secbase = tp.tv_sec;
294        return tp.tv_usec/1000000.0;
295    }
296
297    return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
298}
299
300// =======================================================================
301// Sleeps for microseconds
302// =======================================================================
303
304static volatile int oktogo;
305
306void alarm_handler(int x)
307{
308	oktogo=1;
309}
310
311void Sys_LineRefresh(void)
312{
313}
314
315void floating_point_exception_handler(int whatever)
316{
317//	Sys_Warn("floating point exception\n");
318	signal(SIGFPE, floating_point_exception_handler);
319}
320
321char *Sys_ConsoleInput(void)
322{
323#if 0
324    static char text[256];
325    int     len;
326
327	if (cls.state == ca_dedicated) {
328		len = read (0, text, sizeof(text));
329		if (len < 1)
330			return NULL;
331		text[len-1] = 0;    // rip off the /n and terminate
332
333		return text;
334	}
335#endif
336	return NULL;
337}
338
339#if !id386
340void Sys_HighFPPrecision (void)
341{
342}
343
344void Sys_LowFPPrecision (void)
345{
346}
347#endif
348
349int		skipframes;
350
351int main (int c, char **v)
352{
353
354	double		time, oldtime, newtime;
355	quakeparms_t parms;
356	int j;
357
358//	static char cwd[1024];
359
360//	signal(SIGFPE, floating_point_exception_handler);
361	signal(SIGFPE, SIG_IGN);
362
363	memset(&parms, 0, sizeof(parms));
364
365	COM_InitArgv(c, v);
366	parms.argc = com_argc;
367	parms.argv = com_argv;
368
369	parms.memsize = 16*1024*1024;
370
371	j = COM_CheckParm("-mem");
372	if (j)
373		parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
374	parms.membase = malloc (parms.memsize);
375
376	parms.basedir = basedir;
377// caching is disabled by default, use -cachedir to enable
378//	parms.cachedir = cachedir;
379
380	noconinput = COM_CheckParm("-noconinput");
381	if (!noconinput)
382		fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
383
384	if (COM_CheckParm("-nostdout"))
385		nostdout = 1;
386
387	Sys_Init();
388
389    Host_Init(&parms);
390
391    oldtime = Sys_DoubleTime ();
392    while (1)
393    {
394// find time spent rendering last frame
395        newtime = Sys_DoubleTime ();
396        time = newtime - oldtime;
397
398		Host_Frame(time);
399		oldtime = newtime;
400    }
401
402}
403
404
405/*
406================
407Sys_MakeCodeWriteable
408================
409*/
410void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
411{
412
413	int r;
414	unsigned long addr;
415	int psize = getpagesize();
416
417	addr = (startaddr & ~(psize-1)) - psize;
418
419//	fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
420//			addr, startaddr+length, length);
421
422	r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
423
424	if (r < 0)
425    		Sys_Error("Protection change failed\n");
426
427}
428
429