ref: e7f55e32736cd1360a7135fda5a7ca4d97c45520
dir: /sys_plan9.c/
#include "quakedef.h" #include <thread.h> int mainstacksize = 1*1024*1024; char *netmtpt = "/net"; char *game; int debug; static const char *disabled[32]; static int ndisabled; int qctz(unsigned x) { unsigned r; if(x == 0) r = 32; else for(r = 0; (x & 1) == 0; x >>= 1, r++); return r; } bool isdisabled(char *s) { int i; for(i = 0; i < ndisabled; i++){ if(strcmp(disabled[i], s) == 0) return true; } return false; } int sys_mkdir(char *path) { int d; if(access(path, AEXIST) == 0) return 0; if((d = create(path, OREAD, DMDIR|0777)) < 0){ Con_DPrintf("Sys_mkdir: create: %r\n"); return -1; } close(d); return 0; } char * sys_timestamp(void) { static char ts[32]; Tm *tm; long t; if((t = time(nil)) < 0 || (tm = localtime(t)) == nil) return nil; snprint(ts, sizeof(ts), "%04d%02d%02d-%02d%02d%02d", tm->year + 1900, tm->mon + 1, tm->mday, tm->hour, tm->min, tm->sec ); return ts; } void sys_snail(bool) { } char * lerr(void) { static char err[ERRMAX]; rerrstr(err, sizeof(err)); return err; } _Noreturn void fatal(char *fmt, ...) { char s[1024]; va_list arg; va_start(arg, fmt); vseprint(s, s+sizeof s, fmt, arg); va_end(arg); Host_Shutdown(); sysfatal("%s", s); } void * emalloc(long n) { void *p; if(p = mallocz(n, 1), p == nil) sysfatal("emalloc %r"); setmalloctag(p, getcallerpc(&n)); return p; } vlong flen(int fd) { vlong l; Dir *d; if((d = dirfstat(fd)) == nil) /* file assumed extant and readable */ sysfatal("flen: %r"); l = d->length; free(d); return l; } double dtime(void) { return nanosec() / 1000000000.0; } void game_shutdown(void) { stopfb(); Host_Shutdown(); threadexitsall(nil); } static void croak(void *, char *note) { if(strncmp(note, "sys:", 4) == 0){ IN_Grabm(0); threadkillgrp(0); } noted(NDFLT); } static void usage(void) { fprint(2, "usage: %s [-d] [-g game] [-m kB] [-x netmtpt] [-N cd|snd]\n", argv0); exits("usage"); } void threadmain(int argc, char **argv) { double t, t´, Δt; char *e; static char *paths[] = { "/sys/games/lib/quake", nil, nil, }; ARGBEGIN{ case 'D': debug = 1; break; case 'd': dedicated = 1; break; case 'g': game = EARGF(usage()); break; case 'x': netmtpt = EARGF(usage()); break; case 'N': if(ndisabled < nelem(disabled)) disabled[ndisabled++] = EARGF(usage()); break; default: usage(); }ARGEND srand(getpid()); /* ignore fp exceptions: rendering shit assumes they are */ setfcr(getfcr() & ~(FPOVFL|FPUNFL|FPINVAL|FPZDIV)); notify(croak); e = getenv("home"); paths[1] = smprint("%s/lib/quake", e); free(e); Host_Init(argc, argv, paths); t = dtime() - 1.0 / Fpsmax; for(;;){ t´ = dtime(); Δt = t´ - t; if(cls.state == ca_dedicated){ if(Δt < sys_ticrate.value) continue; Δt = sys_ticrate.value; } if(Δt > sys_ticrate.value * 2) t = t´; else t += Δt; Host_Frame(Δt); } }