shithub: qk1

ref: b8e4e7db10724ef2fd64ccc21dad5e4a2f3fb811
dir: /sys_unix.c/

View raw version
#include "quakedef.h"
#include "parg.h"
#include <time.h>
#include <errno.h>
#include <fenv.h>

char *game;
int debug;
char lasterr[256] = {0};
static const char *disabled[32];
static int ndisabled;

bool
isdisabled(char *s)
{
	int i;

	for(i = 0; i < ndisabled; i++){
		if(strcmp(disabled[i], s) == 0)
			return true;
	}
	return false;
}

char *
lerr(void)
{
	static char lasterrcopy[256];
	if(*lasterr == 0 && errno != 0)
		return strerror(errno);
	strcpy(lasterrcopy, lasterr);
	return lasterrcopy;
}

int
sys_mkdir(char *path)
{
	return (mkdir(path, 0770) == 0 || errno == EEXIST) ? 0 : -1;
}

char *
sys_timestamp(void)
{
	static char ts[32];
	struct tm *tm;
	time_t t;

	if((t = time(nil)) == (time_t)-1 || (tm = localtime(&t)) == nil)
		return nil;
	snprint(ts, sizeof(ts),
		"%04d%02d%02d-%02d%02d%02d",
		tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec
	);

	return ts;
}

void
fatal(char *fmt, ...)
{
	va_list arg;

	va_start(arg, fmt);
	vfprintf(stderr, fmt, arg);
	va_end(arg);
	Host_Shutdown();
	exit(1);
}

void *
emalloc(long n)
{
	void *p;

	if(p = calloc(1, n), p == nil)
		fatal("emalloc");
	setmalloctag(p, getcallerpc(&n));
	return p;
}

u64int
nanosec(void)
{
	static time_t sec0;
	struct timespec t;

	if(clock_gettime(CLOCK_MONOTONIC, &t) != 0)
		fatal("clock_gettime");
	if(sec0 == 0)
		sec0 = t.tv_sec;
	t.tv_sec -= sec0;
	return t.tv_sec*1000000000ULL + t.tv_nsec;
}

double
dtime(void)
{
	return nanosec()/1000000000.0;
}

void
game_shutdown(void)
{
	stopfb();
	Host_Shutdown();
	exit(0);
}

int
main(int argc, char **argv)
{
	double t, t2, dt;
	struct parg_state ps;
	int c, nargs, i;
	static char *paths[8] = {0};

	i = 0;
	paths[i++] = ".";
	paths[i++] = "/usr/games/quake";
	paths[i++] = strdup(va("%s/.quake", getenv("HOME")));

	parg_init(&ps);
	nargs = 0;
	while((c = parg_getopt(&ps, argc, argv, "b:Ddg:N:")) >= 0){
		switch(c){
		case 1:
			argv[nargs++] = (char*)ps.optarg;
			break;
		case 'b':
			if(i < nelem(paths)-2)
				paths[i++] = (char*)ps.optarg;
			break;
		case 'N':
			if(ndisabled < nelem(disabled))
				disabled[ndisabled++] = ps.optarg;
			break;
		case 'D':
			debug++;
			break;
		case 'd':
			dedicated = 1;
			break;
		case 'g':
			game = (char*)ps.optarg;
			break;
		case 'h':
			fprintf(stderr, "usage: qk1 [-g game]\n");
			return 0;
			break;
		case '?':
			fprintf(stderr, "unknown option -%c\n", ps.optopt);
			return 1;
			break;
		default:
			fprintf(stderr, "unhandled option -%c\n", c);
			return 1;
			break;
		}
	}

	m_random_init(time(nil));
	srand(time(nil));

	paths[i] = sys_wrpath();
	Host_Init(nargs, argv, paths);

	fesetround(FE_TOWARDZERO);

	t = dtime() - 1.0 / Fpsmax;
	for(;;){
		t2 = dtime();
		dt = t2 - t;
		if(cls.state == ca_dedicated){
			if(dt < sys_ticrate.value)
				continue;
			dt = sys_ticrate.value;
		}
		if(dt > sys_ticrate.value * 2)
			t = t2;
		else
			t += dt;
		Host_Frame(dt);
	}
	return 0;
}