#include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __WIN32__ #include #include #include #include #include #endif #include "quakedef.h" qboolean isDedicated; int noconinput = 0; #if defined (USERPREF_DIR) char *prefdir= ".tenebrae"; #endif #if defined (BASEDIR) /* - DC - won't work without this */ #define macro_string(x) _macro_string(x) #define _macro_string(x) #x char *basedir = macro_string(BASEDIR); #undef macro_string #undef _macro_string #else char *basedir = "."; #endif char *cachedir = "/tmp"; cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display cvar_t sys_nostdout = {"sys_nostdout","0"}; // ======================================================================= // General routines // ======================================================================= void Sys_DebugNumber(int y, int val) { } void Sys_Printf (char *fmt, ...) { va_list argptr; char text[4096]; va_start (argptr,fmt); vsprintf (text,fmt,argptr); va_end (argptr); fprintf(stderr, "%s", text); //Con_Print (text); } void Sys_Quit (void) { Host_Shutdown(); exit(0); } void Sys_Init(void) { #ifdef id386 Sys_SetFPCW(); #endif } #ifndef id386 /* ================ Sys_LowFPPrecision ================ */ void Sys_LowFPPrecision (void) { // causes weird problems on Nextstep } /* ================ Sys_HighFPPrecision ================ */ void Sys_HighFPPrecision (void) { // causes weird problems on Nextstep } #endif // !id386 void Sys_Error (char *error, ...) { va_list argptr; char string[4096]; va_start (argptr,error); vsprintf (string,error,argptr); va_end (argptr); fprintf(stderr, "Error: %s\n", string); Host_Shutdown (); exit (1); } void Sys_Warn (char *warning, ...) { va_list argptr; char string[4096]; va_start (argptr,warning); vsprintf (string,warning,argptr); va_end (argptr); fprintf(stderr, "Warning: %s", string); } /* =============================================================================== FILE IO =============================================================================== */ #define MAX_HANDLES 256 FILE *sys_handles[MAX_HANDLES]; int findhandle (void) { int i; for (i=1 ; i= 0 ) { fclose (sys_handles[handle]); sys_handles[handle] = NULL; } } void Sys_FileSeek (int handle, int position) { if ( handle >= 0 ) { fseek (sys_handles[handle], position, SEEK_SET); } } int Sys_FileRead (int handle, void *dst, int count) { char *data; int size, done; size = 0; if ( handle >= 0 ) { data = dst; while ( count > 0 ) { done = fread (data, 1, count, sys_handles[handle]); if ( done == 0 ) { break; } data += done; count -= done; size += done; } } return size; } int Sys_FileWrite (int handle, void *src, int count) { char *data; int size, done; size = 0; if ( handle >= 0 ) { data = src; while ( count > 0 ) { done = fread (data, 1, count, sys_handles[handle]); if ( done == 0 ) { break; } data += done; count -= done; size += done; } } return size; } int Sys_FileTime (char *path) { FILE *f; f = fopen(path, "rb"); if (f) { fclose(f); return 1; } return -1; } void Sys_mkdir (char *path) { #ifdef __WIN32__ mkdir (path); #else mkdir (path, 0777); #endif } void Sys_Strtime(char *buf) { struct tm *tm_; static time_t t_; time(&t_); tm_=gmtime(&t_); sprintf(buf,"%02d:%02d:%02d",tm_->tm_hour,tm_->tm_min,tm_->tm_sec); } void Sys_DebugLog(char *file, char *fmt, ...) { va_list argptr; static char data[4096]; FILE *fp; va_start(argptr, fmt); vsprintf(data, fmt, argptr); va_end(argptr); fp = fopen(file, "a"); fwrite(data, strlen(data), 1, fp); fclose(fp); } double Sys_FloatTime (void) { #ifdef __WIN32__ static int starttime = 0; if ( ! starttime ) starttime = clock(); return (clock()-starttime)*1.0/1024; #else struct timeval tp; struct timezone tzp; static int secbase; gettimeofday(&tp, &tzp); if (!secbase) { secbase = tp.tv_sec; return tp.tv_usec/1000000.0; } return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; #endif } // ======================================================================= // Sleeps for microseconds // ======================================================================= static volatile int oktogo; void alarm_handler(int x) { oktogo=1; } byte *Sys_ZoneBase (int *size) { char *QUAKEOPT = getenv("QUAKEOPT"); *size = 0xc00000; if (QUAKEOPT) { while (*QUAKEOPT) if (tolower(*QUAKEOPT++) == 'm') { *size = atof(QUAKEOPT) * 1024*1024; break; } } return malloc (*size); } void Sys_LineRefresh(void) { } void Sys_Sleep(void) { SDL_Delay(1); } void floating_point_exception_handler(int whatever) { // Sys_Warn("floating point exception\n"); signal(SIGFPE, floating_point_exception_handler); } void moncontrol(int x) { } // - DC - create user pref directory #if defined (USERPREF_DIR) char *Sys_InitUserDir(void) { char *home; char *userdir; struct stat stat_buf; int ulen; home = getenv("HOME"); if (!home){ Sys_Error("Environment variable HOME not found.\n"); } ulen = strlen(home)+strlen(prefdir); userdir = (char *)malloc(ulen+2); strncpy(userdir,home,ulen); if (home[strlen(home)-1]!='/'){ ulen++; strncat(userdir,"/",ulen); } if (stat(userdir,&stat_buf)){ Sys_Error("could not stat %s\n",userdir); } strncat(userdir,prefdir,ulen); userdir[ulen]=0; if (stat(userdir,&stat_buf)){ if (errno == ENOENT) Sys_mkdir(userdir); else Sys_Error("error while stating %s\n",userdir); } if (!S_ISDIR(stat_buf.st_mode)) Sys_Error("%s is not a directory\n",userdir); return userdir; } #endif int main (int c, char **v) { double time, oldtime, newtime; quakeparms_t parms; extern int vcrFile; extern int recording; static int frame; int mb_mem_size=50; int j; moncontrol(0); // signal(SIGFPE, floating_point_exception_handler); signal(SIGFPE, SIG_IGN); COM_InitArgv(c, v); parms.argc = com_argc; parms.argv = com_argv; j = COM_CheckParm ("-heapsize"); if (j) mb_mem_size = (int) (Q_atof (com_argv[j + 1])); parms.memsize = mb_mem_size*1024*1024; parms.membase = malloc (parms.memsize); // not enough memory !! if (!parms.membase){ Sys_Error("Not enough memory - asked for %d - change with -heapsize \n",mb_mem_size); } #if defined (USERPREF_DIR) parms.userdir = Sys_InitUserDir (); #endif parms.basedir = basedir; // caching is disabled by default, use -cachedir to enable parms.cachedir = ""; Sys_Init(); Host_Init(&parms); Cvar_RegisterVariable (&sys_nostdout); oldtime = Sys_FloatTime () - 0.1; while (1) { // find time spent rendering last frame newtime = Sys_FloatTime (); time = newtime - oldtime; if (cls.state == ca_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate.value && (vcrFile == -1 || recording) ) { SDL_Delay (1); continue; // not time to run a server only tic yet } time = sys_ticrate.value; } if (time > sys_ticrate.value*2) oldtime = newtime; else oldtime += time; if (++frame > 10) moncontrol(1); // profile only while we do each Quake frame Host_Frame (time); moncontrol(0); // graphic debugging aids if (sys_linerefresh.value) Sys_LineRefresh (); } } /* ================ Sys_MakeCodeWriteable ================ */ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) { int r; unsigned long addr; int psize = getpagesize(); fprintf(stderr, "writable code %lx-%lx\n", startaddr, startaddr+length); addr = startaddr & ~(psize-1); r = mprotect((char*)addr, length + startaddr - addr, 7); if (r < 0) Sys_Error("Protection change failed\n"); }