shithub: qk1

Download patch

ref: 604d47937d45ebba3ee3b6053bd796b8513e6a3f
parent: 4d90db49e2d2c46234b951f64fc73e412ca85e5a
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Nov 5 22:20:57 EST 2023

portable: 9front + linux

diff: cannot open b/unix//null: file does not exist: 'b/unix//null'
--- a/Makefile
+++ b/Makefile
@@ -1,32 +1,27 @@
-BASEVERSION=1.09
-VERSION=1.09
-ARCH=$(shell uname -m)
-BASE_CFLAGS=-Dstricmp=strcasecmp
-DEBUG_CFLAGS=$(BASE_CFLAGS) -ggdb -O0 -trigraphs -Wall -Wextra -m32
-LDFLAGS=-lm
-XLDFLAGS= -lX11 -lXext -lXxf86dga
-XCFLAGS=-DX11
-DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
-DO_X11_CC=$(CC) $(CFLAGS) $(XCFLAGS) -o $@ -c $<
-DO_O_CC=$(CC) -O $(CFLAGS) -o $@ -c $<
-DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
-CFLAGS=$(DEBUG_CFLAGS)
+TARG=qk1
+DESTDIR?=
+PREFIX?=/usr/local
+BIN=${DESTDIR}${PREFIX}/bin
+MAN=${DESTDIR}${PREFIX}/share/man/man1
+SDL2_CFLAGS=$$(pkg-config --cflags sdl2)
+SDL2_LDFLAGS=$$(pkg-config --libs sdl2)
+CFLAGS?=-O2 -pipe -g -Wall
+CFLAGS+=-fms-extensions -Iunix -I. ${SDL2_CFLAGS}
+LDFLAGS?=
+LDFLAGS+=-lm ${SDL2_LDFLAGS}
 
-all: qk1
-
-X11_OBJS =\
+OBJS=\
+	chase.o\
 	cl_demo.o\
 	cl_input.o\
 	cl_main.o\
 	cl_parse.o\
 	cl_tent.o\
-	chase.o\
 	cmd.o\
 	common.o\
 	console.o\
-	crc.o\
 	cvar.o\
-	draw.o\
+	d_alpha.o\
 	d_edge.o\
 	d_fill.o\
 	d_init.o\
@@ -39,347 +34,78 @@
 	d_surf.o\
 	d_vars.o\
 	d_zpoint.o\
+	dotproduct.o\
+	draw.o\
 	host.o\
 	host_cmd.o\
 	keys.o\
-	menu.o\
 	mathlib.o\
+	menu.o\
 	model.o\
-	net_dgrm.o\
 	net_loop.o\
 	net_main.o\
-	net_vcr.o\
-	net_udp.o\
-	net_bsd.o\
-	nonintel.o\
+	pal.o\
 	pr_cmds.o\
 	pr_edict.o\
 	pr_exec.o\
+	protocol.o\
 	r_aclip.o\
 	r_alias.o\
 	r_bsp.o\
-	r_light.o\
 	r_draw.o\
-	r_efrag.o\
 	r_edge.o\
-	r_misc.o\
+	r_efrag.o\
+	r_light.o\
 	r_main.o\
+	r_misc.o\
+	r_part.o\
 	r_sky.o\
 	r_sprite.o\
 	r_surf.o\
-	r_part.o\
 	r_vars.o\
-	screen.o\
 	sbar.o\
+	screen.o\
+	span.o\
+	span_alpha.o\
 	sv_main.o\
-	sv_phys.o\
 	sv_move.o\
+	sv_phys.o\
 	sv_user.o\
-	zone.o\
+	unix/cd.o\
+	unix/fs.o\
+	unix/in.o\
+	unix/net_udp.o\
+	unix/qk1.o\
+	unix/seprint.o\
+	unix/snd.o\
+	unix/vid.o\
 	view.o\
 	wad.o\
 	world.o\
-	cd_linux.o\
-	sys_linux.o\
-	vid_x.o\
-	snd_dma.o\
-	snd_mem.o\
-	snd_mix.o\
-	snd_linux.o\
-	d_draw.o\
-	d_draw16.o\
-	d_parta.o\
-	d_polysa.o\
-	d_scana.o\
-	d_spr8.o\
-	d_varsa.o\
-	math.o\
-	r_aliasa.o\
-	r_drawa.o\
-	r_edgea.o\
-	r_varsa.o\
-	surf16.o\
-	surf8.o\
-	worlda.o\
-	r_aclipa.o\
-	snd_mixa.o\
-	sys_dosa.o\
+	zone.o\
 
-qk1: $(X11_OBJS)
-	$(CC) $(CFLAGS) -o $@ $(X11_OBJS) $(XLDFLAGS) $(LDFLAGS)
+.PHONY: all default install uninstall clean
 
-####
+all: default
 
-cl_demo.o :  cl_demo.c
-	$(DO_X11_CC)
+default: ${TARG}
 
-cl_input.o : cl_input.c
-	$(DO_X11_CC)
+install: ${TARG} ${TARG}.1
+	install -d ${BIN}
+	install -m 755 ${TARG} ${BIN}
+	install -d ${MAN}
+	install -m 644 ${TARG}.1 ${MAN}
 
-cl_main.o :  cl_main.c
-	$(DO_X11_CC)
-
-cl_parse.o : cl_parse.c
-	$(DO_X11_CC)
+uninstall:
+	rm -f ${BIN}/${TARG}
+	rm -f ${MAN}/${TARG}.1
 
-cl_tent.o :  cl_tent.c
-	$(DO_X11_CC)
+${TARG}: ${OBJS}
+	${CC} -o $@ ${OBJS} ${LDFLAGS}
 
-chase.o :    chase.c
-	$(DO_X11_CC)
+.SUFFIXES: .c .o
+.c.o:
+	${CC} -o $@ -c $< ${CFLAGS}
 
-cmd.o :      cmd.c
-	$(DO_X11_CC)
-
-common.o :   common.c
-	$(DO_X11_CC)
-
-console.o :  console.c
-	$(DO_X11_CC)
-
-crc.o :      crc.c
-	$(DO_X11_CC)
-
-cvar.o :     cvar.c
-	$(DO_X11_CC)
-
-draw.o :     draw.c
-	$(DO_X11_CC)
-
-d_edge.o :   d_edge.c
-	$(DO_X11_CC)
-
-d_fill.o :   d_fill.c
-	$(DO_X11_CC)
-
-d_init.o :   d_init.c
-	$(DO_X11_CC)
-
-d_modech.o : d_modech.c
-	$(DO_X11_CC)
-
-d_part.o :   d_part.c
-	$(DO_X11_CC)
-
-d_polyse.o : d_polyse.c
-	$(DO_X11_CC)
-
-d_scan.o :   d_scan.c
-	$(DO_X11_CC)
-
-d_sky.o :    d_sky.c
-	$(DO_X11_CC)
-
-d_sprite.o : d_sprite.c
-	$(DO_X11_CC)
-
-d_surf.o :   d_surf.c
-	$(DO_X11_CC)
-
-d_vars.o :   d_vars.c
-	$(DO_X11_CC)
-
-d_zpoint.o : d_zpoint.c
-	$(DO_X11_CC)
-
-host.o :     host.c
-	$(DO_X11_CC)
-
-host_cmd.o : host_cmd.c
-	$(DO_X11_CC)
-
-keys.o :     keys.c
-	$(DO_X11_CC)
-
-menu.o :     menu.c
-	$(DO_X11_CC)
-
-mathlib.o :  mathlib.c
-	$(DO_X11_CC)
-
-model.o :    model.c
-	$(DO_X11_CC)
-
-net_dgrm.o : net_dgrm.c
-	$(DO_X11_CC)
-
-net_loop.o : net_loop.c
-	$(DO_X11_CC)
-
-net_main.o : net_main.c
-	$(DO_X11_CC)
-
-net_vcr.o :  net_vcr.c
-	$(DO_X11_CC)
-
-net_udp.o :  net_udp.c
-	$(DO_X11_CC)
-
-net_bsd.o :  net_bsd.c
-	$(DO_X11_CC)
-
-nonintel.o : nonintel.c
-	$(DO_X11_CC)
-
-pr_cmds.o :  pr_cmds.c
-	$(DO_X11_CC)
-
-pr_edict.o : pr_edict.c
-	$(DO_X11_CC)
-
-pr_exec.o :  pr_exec.c
-	$(DO_X11_CC)
-
-r_aclip.o :  r_aclip.c
-	$(DO_X11_CC)
-
-r_alias.o :  r_alias.c
-	$(DO_X11_CC)
-
-r_bsp.o :    r_bsp.c
-	$(DO_X11_CC)
-
-r_light.o :  r_light.c
-	$(DO_X11_CC)
-
-r_draw.o :   r_draw.c
-	$(DO_X11_CC)
-
-r_efrag.o :  r_efrag.c
-	$(DO_X11_CC)
-
-r_edge.o :   r_edge.c
-	$(DO_X11_CC)
-
-r_misc.o :   r_misc.c
-	$(DO_X11_CC)
-
-r_main.o :   r_main.c
-	$(DO_X11_CC)
-
-r_sky.o :    r_sky.c
-	$(DO_X11_CC)
-
-r_sprite.o : r_sprite.c
-	$(DO_X11_CC)
-
-r_surf.o :   r_surf.c
-	$(DO_X11_CC)
-
-r_part.o :   r_part.c
-	$(DO_X11_CC)
-
-r_vars.o :   r_vars.c
-	$(DO_X11_CC)
-
-screen.o :   screen.c
-	$(DO_X11_CC)
-
-sbar.o :     sbar.c
-	$(DO_X11_CC)
-
-sv_main.o :  sv_main.c
-	$(DO_X11_CC)
-
-sv_phys.o :  sv_phys.c
-	$(DO_X11_CC)
-
-sv_move.o :  sv_move.c
-	$(DO_X11_CC)
-
-sv_user.o :  sv_user.c
-	$(DO_X11_CC)
-
-zone.o	:   zone.c
-	$(DO_X11_CC)
-
-view.o	:   view.c
-	$(DO_X11_CC)
-
-wad.o :      wad.c
-	$(DO_X11_CC)
-
-world.o :    world.c
-	$(DO_X11_CC)
-
-cd_linux.o : cd_linux.c
-	$(DO_X11_CC)
-
-sys_linux.o :sys_linux.c
-	$(DO_X11_CC)
-
-vid_x.o: vid_x.c
-	$(DO_O_CC)
-
-snd_dma.o :  snd_dma.c
-	$(DO_X11_CC)
-
-snd_mem.o :  snd_mem.c
-	$(DO_X11_CC)
-
-snd_mix.o :  snd_mix.c
-	$(DO_X11_CC)
-
-snd_linux.o :snd_linux.c
-	$(DO_X11_CC)
-
-d_copy.o :   d_copy.s
-	$(DO_AS)
-
-d_draw.o :   d_draw.s
-	$(DO_AS)
-
-d_draw16.o : d_draw16.s
-	$(DO_AS)
-
-d_parta.o :  d_parta.s
-	$(DO_AS)
-
-d_polysa.o : d_polysa.s
-	$(DO_AS)
-
-d_scana.o :  d_scana.s
-	$(DO_AS)
-
-d_spr8.o :   d_spr8.s
-	$(DO_AS)
-
-d_varsa.o :  d_varsa.s
-	$(DO_AS)
-
-math.o :     math.s
-	$(DO_AS)
-
-r_aliasa.o : r_aliasa.s
-	$(DO_AS)
-
-r_drawa.o :  r_drawa.s
-	$(DO_AS)
-
-r_edgea.o :  r_edgea.s
-	$(DO_AS)
-
-r_varsa.o :  r_varsa.s
-	$(DO_AS)
-
-surf16.o :   surf16.s
-	$(DO_AS)
-
-surf8.o :    surf8.s
-	$(DO_AS)
-
-worlda.o :   worlda.s
-	$(DO_AS)
-
-r_aclipa.o : r_aclipa.s
-	$(DO_AS)
-
-snd_mixa.o : snd_mixa.s
-	$(DO_AS)
-
-sys_dosa.o : sys_dosa.s
-	$(DO_AS)
-
-
 clean:
-	rm -f qk1 $(X11_OBJS)
+	rm -f ${TARG} ${OBJS}
--- a/bspfile.h
+++ b/bspfile.h
@@ -33,7 +33,11 @@
 #define BSP2VERSION ('B'|'S'<<8|'P'<<16|'2'<<24)
 #define	TOOLVERSION	2
 
+#ifdef __plan9__
 #pragma pack on
+#else
+#pragma pack(1)
+#endif
 
 typedef struct
 {
@@ -239,7 +243,11 @@
 	byte		ambient_level[Namb];
 } bsp2_dleaf_t;
 
+#ifdef __plan9__
 #pragma pack off
+#else
+#pragma pack(0)
+#endif
 
 
 //============================================================================
--- a/cl_input.c
+++ b/cl_input.c
@@ -163,25 +163,13 @@
 	val = 0;
 	
 	if (impulsedown && !impulseup)
-		if (down)
-			val = 0.5;	// pressed and held this frame
-		else
-			val = 0;	//	I_Error ();
-	if (impulseup && !impulsedown)
-		if (down)
-			val = 0;	//	I_Error ();
-		else
-			val = 0;	// released this frame
-	if (!impulsedown && !impulseup)
-		if (down)
-			val = 1.0;	// held the entire frame
-		else
-			val = 0;	// up the entire frame
-	if (impulsedown && impulseup)
-		if (down)
-			val = 0.75;	// released and re-pressed this frame
-		else
-			val = 0.25;	// pressed and released this frame
+		val = down ? 0.5 : 0;
+	else if (impulseup && !impulsedown)
+		val = 0;
+	else if (!impulsedown && !impulseup)
+		val = down ? 1.0 : 0;
+	else if (impulsedown && impulseup)
+		val = down ? 0.75 : 0.25;
 
 	key->state &= 1;		// clear impulses
 	
--- a/common.c
+++ b/common.c
@@ -323,14 +323,15 @@
 
 //===========================================================================
 
-void
-Arr_AllocExtra(void **arr, int *nel, int needextra)
+void *
+Arr_AllocExtra(void *arr, int *nel, int needextra)
 {
 	while(needextra > 0){
-		*arr = Hunk_Double(*arr);
+		arr = Hunk_Double(arr);
 		needextra -= *nel;
 		*nel *= 2;
 	}
+	return arr;
 }
 
 void
--- a/common.h
+++ b/common.h
@@ -1,4 +1,4 @@
-void Arr_AllocExtra(void **arr, int *nel, int needextra);
+void *Arr_AllocExtra(void *arr, int *nel, int needextra);
 
 typedef struct sizebuf_s
 {
@@ -126,4 +126,6 @@
 
 extern qboolean		standard_quake, rogue, hipnotic;
 
+#ifdef __plan9__
 #pragma varargck	argpos	va	1
+#endif
--- a/console.c
+++ b/console.c
@@ -342,8 +342,8 @@
 	va_end (argptr);
 
 	Con_Printf ("%s", msg);
-	if(developer.value > 1)
-		write(2, msg, n);
+	if(developer.value > 1 && write(2, msg, n) < 0)
+		setcvar("developer", "0");
 }
 
 /*
--- a/console.h
+++ b/console.h
@@ -20,4 +20,7 @@
 void Con_ClearNotify (void);
 void Con_ToggleConsole_f (void);
 
+#ifdef __plan9__
 #pragma varargck	argpos	Con_Printf	1
+#pragma varargck	argpos	Con_DPrintf	1
+#endif
--- a/cvar.c
+++ b/cvar.c
@@ -162,6 +162,6 @@
 {
 	char u[32];
 
-	sprint(u, "%f", v);
+	snprint(u, sizeof(u), "%f", v);
 	setcvar(k, u);
 }
--- a/d_edge.c
+++ b/d_edge.c
@@ -7,7 +7,6 @@
 static int	miplevel;
 
 float		scale_for_mip;
-int			screenwidth;
 int			ubasestep, errorterm, erroradjustup, erroradjustdown;
 int			vstartscan;
 
--- a/d_local.h
+++ b/d_local.h
@@ -47,8 +47,8 @@
 extern float	d_sdivzstepv, d_tdivzstepv, d_zistepv;
 extern float	d_sdivzorigin, d_tdivzorigin, d_ziorigin;
 
-fixed16_t	sadjust, tadjust;
-fixed16_t	bbextents, bbextentt;
+extern fixed16_t	sadjust, tadjust;
+extern fixed16_t	bbextents, bbextentt;
 
 void D_DrawSpans8 (espan_t *pspans);
 void D_DrawSpans16 (espan_t *pspans, byte alpha);
@@ -60,7 +60,6 @@
 void D_DrawSkyScans16 (espan_t *pspan);
 
 void R_ShowSubDiv (void);
-void (*prealspandrawer)(void);
 surfcache_t	*D_CacheSurface (msurface_t *surface, int miplevel);
 
 extern int D_MipLevelForScale (float scale);
--- a/d_scan.c
+++ b/d_scan.c
@@ -323,7 +323,7 @@
 			WRITEFENCE(-3);
 			WRITEFENCE(-2);
 			WRITEFENCE(-1);
-			USED(s, t);
+			USED(s); USED(t);
 
 			s = snext;
 			t = tnext;
@@ -373,7 +373,7 @@
 			case  3: WRITEFENCE(-3);
 			case  2: WRITEFENCE(-2);
 			case  1: WRITEFENCE(-1);
-			USED(izi, s, t);
+			USED(izi); USED(s); USED(t);
 			}
 		}
 	}
--- a/dotproduct.c
+++ b/dotproduct.c
@@ -1,5 +1,5 @@
 float
-DotProduct(float v1[3], float v2[3])
+DotProduct(const float v1[3], const float v2[3])
 {
 	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
 }
--- a/fns.h
+++ b/fns.h
@@ -52,7 +52,9 @@
 void*	emalloc(ulong);
 vlong	flen(int);
 double	dtime(void);
-void	shutdown(void);
+void	game_shutdown(void);
 uvlong	nanosec(void);
 
+#ifdef __plan9__
 #pragma varargck	argpos	fatal	1
+#endif
--- a/fs.c
+++ b/fs.c
@@ -228,15 +228,6 @@
 	return v << 8 | get8(bf);
 }
 
-static u32int
-get32b(Biobuf *bf)
-{
-	u32int v;
-
-	v = get16(bf);
-	return v << 16 | get16(bf);
-}
-
 static void
 ewrite(Biobuf *bf, void *u, long n)
 {
@@ -265,6 +256,7 @@
 	put32(bf, w.u);
 }
 
+#ifdef __plan9__
 static vlong
 bsize(Biobuf *bf)
 {
@@ -278,7 +270,19 @@
 	free(d);
 	return n;
 }
+#else
+static vlong
+bsize(Biobuf *bf)
+{
+	struct stat st;
 
+	if(fstat(Bfildes(bf), &st) != 0)
+		fatal("bstat");
+	return st.st_size;
+}
+#endif
+
+#ifdef __plan9__
 static int
 mkdir(char *path)
 {
@@ -293,6 +297,9 @@
 	close(d);
 	return 0;
 }
+#else
+#define mkdir(p) mkdir(p, 0770)
+#endif
 
 static int
 mkpath(char *path)
@@ -330,7 +337,7 @@
 static Biobuf *
 openlmp(char *f, int *len)
 {
-	char d[Nfspath];
+	char d[Nfspath+1];
 	Biobuf *bf;
 	Paklist *pl;
 	Pak *p;
@@ -830,7 +837,7 @@
 		notid1 = 1;
 	l = Hunk_Alloc(nlmp * sizeof *l);
 	p = Hunk_Alloc(sizeof *p);
-	strncpy(p->f, f, sizeof(p->f)-1);
+	snprint(p->f, sizeof(p->f), "%s", f);
 	p->bf = bf;
 	p->l = l;
 	p->e = l + nlmp;
--- a/host_cmd.c
+++ b/host_cmd.c
@@ -24,7 +24,7 @@
 	CL_Disconnect ();
 	Host_ShutdownServer(false);		
 
-	shutdown ();
+	game_shutdown ();
 }
 
 
--- a/mathlib.c
+++ b/mathlib.c
@@ -5,7 +5,6 @@
 #include "fns.h"
 
 vec3_t vec3_origin = {0,0,0};
-int nanmask = 255<<23;
 
 /*-----------------------------------------------------------------*/
 
--- a/mathlib.h
+++ b/mathlib.h
@@ -15,12 +15,9 @@
 struct mplane_s;
 
 extern vec3_t vec3_origin;
-extern	int nanmask;
 
 #define Qrint(f) (int)((f) + ((f) >= 0 ? 0.5 : -0.5))
 
-#define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
-
 #define DotProduct_(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
 #define DotProductDouble(x,y) ((double)x[0]*y[0]+(double)x[1]*y[1]+(double)x[2]*y[2])
 #define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
@@ -29,7 +26,7 @@
 
 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
 
-vec_t DotProduct (vec3_t v1, vec3_t v2);
+vec_t DotProduct (const vec3_t v1, const vec3_t v2);
 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out);
 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out);
 void _VectorCopy (vec3_t in, vec3_t out);
--- a/menu.c
+++ b/menu.c
@@ -1473,7 +1473,7 @@
 int		lanConfig_cursor_table [] = {72, 92};
 #define NUM_LANCONFIG_CMDS	2
 
-char	lanConfig_portname[6];
+char	lanConfig_portname[8];
 char	lanConfig_joinname[22];
 
 void M_Menu_LanConfig_f (void)
@@ -1483,7 +1483,7 @@
 	m_entersound = true;
 	if(lanConfig_cursor == -1)
 		lanConfig_cursor = 1;
-	strncpy(lanConfig_portname, myip.srv, sizeof(lanConfig_portname)-1);
+	snprint(lanConfig_portname, sizeof(lanConfig_portname), "%s", myip.srv);
 	m_return_onerror = false;
 	m_return_reason[0] = 0;
 }
--- a/mkfile
+++ b/mkfile
@@ -2,7 +2,7 @@
 
 BIN=/$objtype/bin/games
 TARG=quake
-CFLAGS=$CFLAGS -D__${objtype}__
+CFLAGS=$CFLAGS -D__plan9__
 
 OFILES=\
 	pal`{test -f pal_$objtype.s && echo -n _$objtype}.$O\
--- a/model.c
+++ b/model.c
@@ -638,8 +638,10 @@
 
 	for ( i=0 ; i<count ; i++, in++, out++)
 	{
-		for (j=0 ; j<8 ; j++)
+		for (j=0 ; j<4 ; j++)
 			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+		for (j=0 ; j<4 ; j++)
+			out->vecs[1][j] = LittleFloat (in->vecs[1][j]);
 		len1 = Length (out->vecs[0]);
 		len2 = Length (out->vecs[1]);
 		len1 = (len1 + len2)/2;
@@ -1190,9 +1192,9 @@
 
 		if (i < mod->numsubmodels-1)
 		{	// duplicate the basic information
-			char	name[12];
+			char	name[16];
 
-			sprint (name, "*%d", i+1);
+			snprint(name, sizeof(name), "*%d", i+1);
 			loadmodel = Mod_FindName (name);
 			*loadmodel = *mod;
 			strcpy (loadmodel->name, name);
--- a/model.h
+++ b/model.h
@@ -364,6 +364,6 @@
 void	*Mod_Extradata (model_t *mod);	// handles caching
 void	Mod_TouchModel (char *name);
 
-mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
+mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model);
 byte	*Mod_LeafPVS (mleaf_t *leaf, model_t *model);
 void	Mod_Print(void);
--- a/modelgen.h
+++ b/modelgen.h
@@ -6,7 +6,11 @@
 
 typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t;
 
+#ifdef __plan9__
 #pragma pack on
+#else
+#pragma pack(1)
+#endif
 
 typedef struct {
 	int			ident;
@@ -84,4 +88,8 @@
 #define IDPOLYHEADER	(('O'<<24)+('P'<<16)+('D'<<8)+'I')
 														// little-endian "IDPO"
 
+#ifdef __plan9__
 #pragma pack off
+#else
+#pragma pack(0)
+#endif
--- a/net_main.c
+++ b/net_main.c
@@ -34,6 +34,7 @@
 	Loop_Close,
 	Loop_Shutdown
 	}
+#ifdef __plan9__
 	,
 	{
 	"Datagram",
@@ -49,10 +50,12 @@
 	Datagram_Close,
 	Datagram_Shutdown
 	}
+#endif
 };
-int net_numdrivers = 2;
+int net_numdrivers = 0;
 
 Landrv landrv[MAX_NET_DRIVERS] = {
+#ifdef __plan9__
 	{
 	"UDP",
 	false,
@@ -67,8 +70,9 @@
 	UDP_GetSocketPort,
 	UDP_SetSocketPort
 	}
+#endif
 };
-int net_numlandrivers = 1;
+int net_numlandrivers = 0;
 
 // these two macros are to make the code more readable
 #define sfunc	netdrv[sock->driver]
@@ -540,10 +544,10 @@
 	Cmd_AddCommand ("port", NET_Port_f);
 
 	// initialize all the drivers
-	for(net_driverlevel=0; net_driverlevel<net_numdrivers; net_driverlevel++){
-		if(netdrv[net_driverlevel].Init() < 0)
+	for(net_numdrivers=0; netdrv[net_numdrivers].Init; net_numdrivers++){
+		if(netdrv[net_numdrivers].Init() < 0)
 			continue;
-		netdrv[net_driverlevel].initialized = true;
+		netdrv[net_numdrivers].initialized = true;
 	}
 }
 
--- a/pr_comp.h
+++ b/pr_comp.h
@@ -97,7 +97,11 @@
 	OP_BITOR
 };
 
+#ifdef __plan9__
 #pragma pack on
+#else
+#pragma pack(1)
+#endif
 
 typedef struct statement_s
 {
@@ -159,4 +163,8 @@
 	int		entityfields;
 } dprograms_t;
 
+#ifdef __plan9__
 #pragma pack off
+#else
+#pragma pack(0)
+#endif
--- a/pr_edict.c
+++ b/pr_edict.c
@@ -444,7 +444,7 @@
 	val = (void *)&pr_globals[ofs];
 	def = ED_GlobalAtOfs(ofs);
 	if (!def)
-		sprint (line,"%d(???)", ofs);
+		sprint (line,"%d(?)", ofs);
 	else
 	{
 		s = PR_ValueString (def->type, val);
@@ -467,7 +467,7 @@
 	
 	def = ED_GlobalAtOfs(ofs);
 	if (!def)
-		sprint (line,"%d(???)", ofs);
+		sprint (line,"%d(?)", ofs);
 	else
 		sprint (line,"%d(%s)", ofs, PR_Str(def->s_name));
 	
--- a/progs.h
+++ b/progs.h
@@ -120,4 +120,6 @@
 void M_ToggleMenu_f (void);
 void M_Draw (void);
 
+#ifdef __plan9__
 #pragma varargck	argpos	PR_RunError	1
+#endif
--- a/protocol.c
+++ b/protocol.c
@@ -7,7 +7,7 @@
 static void
 MSG_WriteProtocolInfoNQ(sizebuf_t *sb, protocol_t *proto)
 {
-	USED(sb, proto);
+	USED(sb); USED(proto);
 }
 
 static void
--- a/qk1.c
+++ b/qk1.c
@@ -54,7 +54,7 @@
 }
 
 void
-shutdown(void)
+game_shutdown(void)
 {
 	stopfb();
 	Host_Shutdown();
--- a/quakedef.h
+++ b/quakedef.h
@@ -207,6 +207,8 @@
 void Chase_Reset (void);
 void Chase_Update (void);
 
+#ifdef __plan9__
 #pragma varargck	argpos	Host_Error	1
 #pragma varargck	argpos	Host_EndGame	1
 #pragma varargck	argpos	Host_ClientCommands	1
+#endif
--- a/r_bsp.c
+++ b/r_bsp.c
@@ -361,7 +361,7 @@
 				{
 				   lindex = pmodel->surfedges[psurf->firstedge+j];
 
-					if (o = (lindex < 0))
+					if ((o = (lindex < 0)))
 						lindex = -lindex;
 					pedge = &pedges[lindex];
 					pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[o]];
--- a/r_draw.c
+++ b/r_draw.c
@@ -731,6 +731,8 @@
 		}
 	}
 
+	memset(verts, 0, sizeof(verts));
+
 // reconstruct the polygon
 // FIXME: these should be precalculated and loaded off disk
 	pedges = currententity->model->edges;
--- a/r_edge.c
+++ b/r_edge.c
@@ -60,12 +60,12 @@
 {
 	int		v, n;
 
-	Arr_AllocExtra(&r_edges, &r_numallocatededges, r_outofedges);
+	r_edges = Arr_AllocExtra(r_edges, &r_numallocatededges, r_outofedges);
 	edge_p = r_edges;
 	edge_max = &r_edges[r_numallocatededges];
 	r_outofedges = 0;
 
-	Arr_AllocExtra(&surfaces, &r_cnumsurfs, r_outofsurfaces);
+	surfaces = Arr_AllocExtra(surfaces, &r_cnumsurfs, r_outofsurfaces);
 	surf_max = &surfaces[r_cnumsurfs];
 	r_outofsurfaces = 0;
 
@@ -548,7 +548,7 @@
 	espan_t	*basespan_p;
 	surf_t	*s;
 
-	Arr_AllocExtra(&r_basespans, &r_numallocatedbasespans, r_outofspans);
+	r_basespans = Arr_AllocExtra(r_basespans, &r_numallocatedbasespans, r_outofspans);
 	basespan_p = (espan_t *)
 			((uintptr)(r_basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
 	max_span_p = &basespan_p[r_numallocatedbasespans - r_refdef.vrect.width];
--- a/r_main.c
+++ b/r_main.c
@@ -713,7 +713,7 @@
 }
 
 static int
-R_SortEntities(void *a_, void *b_)
+R_SortEntities(const void *a_, const void *b_)
 {
 	entity_t *a, *b;
 	vec3_t v[2];
--- a/r_part.c
+++ b/r_part.c
@@ -53,11 +53,13 @@
 	
 	dist = 64;
 
-if (!avelocities[0][0])
-{
-for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
-avelocities[0][i] = (rand()&255) * 0.01;
-}
+	if(!avelocities[0][0]){
+		for (i=0 ; i<NUMVERTEXNORMALS ; i++){
+			avelocities[i][0] = (rand()&255) * 0.01;
+			avelocities[i][1] = (rand()&255) * 0.01;
+			avelocities[i][2] = (rand()&255) * 0.01;
+		}
+	}
 
 
 	for (i=0 ; i<NUMVERTEXNORMALS ; i++)
@@ -125,11 +127,7 @@
 		dir[i] = MSG_ReadChar () * (1.0/16);
 	msgcount = MSG_ReadByte ();
 	color = MSG_ReadByte ();
-
-if (msgcount == 255)
-	count = 1024;
-else
-	count = msgcount;
+	count = msgcount < 255 ? msgcount : 1024;
 	
 	R_RunParticleEffect (org, dir, color, count);
 }
--- a/sbar.c
+++ b/sbar.c
@@ -360,7 +360,7 @@
 
 int		fragsort[MAX_SCOREBOARD];
 
-char	scoreboardtext[MAX_SCOREBOARD][20];
+char	scoreboardtext[MAX_SCOREBOARD][48];
 int		scoreboardtop[MAX_SCOREBOARD];
 int		scoreboardbottom[MAX_SCOREBOARD];
 int		scoreboardcount[MAX_SCOREBOARD];
@@ -421,7 +421,7 @@
 	{
 		k = fragsort[i];
 		s = &cl.scores[k];
-		sprint (&scoreboardtext[i][1], "%3d %s", s->frags, s->name);
+		snprint (scoreboardtext[i]+1, sizeof(scoreboardtext[i])-1, "%3d %s", s->frags, s->name);
 
 		top = s->colors & 0xf0;
 		bottom = (s->colors & 15) <<4;
--- a/server.h
+++ b/server.h
@@ -203,5 +203,7 @@
 void SV_SaveSpawnparms (void);
 void SV_SpawnServer (char *server);
 
+#ifdef __plan9__
 #pragma varargck	argpos	SV_ClientPrintf	1
 #pragma varargck	argpos	SV_BroadcastPrintf	1
+#endif
--- /dev/null
+++ b/shell.nix
@@ -1,0 +1,8 @@
+with import <nixpkgs> {};
+stdenv.mkDerivation {
+ name = "qk1";
+ buildInputs = with pkgs; [
+  SDL2
+  pkg-config
+ ];
+}
--- a/span.c
+++ b/span.c
@@ -11,7 +11,7 @@
 	}while(0)
 
 void
-dospan(uchar *pdest, uchar *pbase, int s, int t, int sstep, int tstep, int spancount, int cachewidth, u8int alpha, uzint *z, int izi)
+dospan(uchar *pdest, uchar *pbase, int s, int t, int sstep, int tstep, int spancount, int cachewidth)
 {
 	switch(spancount)
 	{
@@ -18,5 +18,5 @@
 	case 16: P; case 15: P; case 14: P; case 13: P; case 12: P; case 11: P; case 10: P; case 9: P;
 	case  8: P; case  7: P; case  6: P; case  5: P; case  4: P; case  3: P; case  2: P; case 1: P;
 	}
-	USED(pdest, s, t, z);
+	USED(pdest); USED(s); USED(t);;
 }
--- a/span_alpha.c
+++ b/span_alpha.c
@@ -21,5 +21,5 @@
 	case 16: P; case 15: P; case 14: P; case 13: P; case 12: P; case 11: P; case 10: P; case 9: P;
 	case  8: P; case  7: P; case  6: P; case  5: P; case  4: P; case  3: P; case  2: P; case 1: P;
 	}
-	USED(pdest, s, t, z);
+	USED(pdest); USED(s); USED(t); USED(z);
 }
--- a/spritegn.h
+++ b/spritegn.h
@@ -2,7 +2,11 @@
 
 #define SPRITE_VERSION	1
 
+#ifdef __plan9__
 #pragma pack on
+#else
+#pragma pack(1)
+#endif
 
 // TODO: shorten these?
 typedef struct {
@@ -46,4 +50,8 @@
 #define IDSPRITEHEADER	(('P'<<24)+('S'<<16)+('D'<<8)+'I')
 														// little-endian "IDSP"
 
+#ifdef __plan9__
 #pragma pack off
+#else
+#pragma pack(0)
+#endif
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -72,12 +72,12 @@
 //
 	for (i=0 ; i<3 ; i++)
 	{
-		if (IS_NAN(ent->v.velocity[i]))
+		if (isnanf(ent->v.velocity[i]))
 		{
 			Con_Printf ("Got a NaN velocity on %s\n", PR_Str(ent->v.classname));
 			ent->v.velocity[i] = 0;
 		}
-		if (IS_NAN(ent->v.origin[i]))
+		if (isnanf(ent->v.origin[i]))
 		{
 			Con_Printf ("Got a NaN origin on %s\n", PR_Str(ent->v.classname));
 			ent->v.origin[i] = 0;
--- /dev/null
+++ b/unix/cd.c
@@ -1,0 +1,51 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+
+cvar_t bgmvolume = {"bgmvolume", "1", 1};
+
+void
+stopcd(void)
+{
+}
+
+void
+pausecd(void)
+{
+}
+
+void
+resumecd(void)
+{
+}
+
+void
+shutcd(void)
+{
+}
+
+void
+stepcd(void)
+{
+}
+
+void
+playcd(int nt, int loop)
+{
+	USED(nt); USED(loop);
+}
+
+static void
+cdcmd(void)
+{
+}
+
+int
+initcd(void)
+{
+	Cvar_RegisterVariable(&bgmvolume);
+	Cmd_AddCommand("cd", cdcmd);
+	return -1;
+}
--- /dev/null
+++ b/unix/fs.c
@@ -1,0 +1,963 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+
+u16int crcn;
+char fsdir[Nfspath];
+
+typedef struct Lump Lump;
+typedef struct Pak Pak;
+typedef struct Paklist Paklist;
+
+enum{
+	Npakhdr = 4+4+4,
+	Npaksz = 56+4+4,
+	Npaklmp = 2048,
+	Npak0lmp = 339,
+	Npak0crc = 0x80d5,
+	Fhunk = 0,
+	Fcache,
+	Fstack
+};
+struct Lump{
+	char fname[Npath];
+	int ofs;
+	int len;
+};
+struct Pak{
+	char fname[Nfspath];
+	FILE *f;
+	Lump *l;
+	Lump *e;
+};
+struct Paklist{
+	char fname[Nfspath];
+	Pak *p;
+	Paklist *pl;
+};
+static Paklist *pkl;
+
+static u16int pop[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x6600, 0x0000, 0x0000, 0x0000, 0x6600, 0x0000,
+	0x0000, 0x0066, 0x0000, 0x0000, 0x0000, 0x0000, 0x0067, 0x0000,
+	0x0000, 0x6665, 0x0000, 0x0000, 0x0000, 0x0000, 0x0065, 0x6600,
+	0x0063, 0x6561, 0x0000, 0x0000, 0x0000, 0x0000, 0x0061, 0x6563,
+	0x0064, 0x6561, 0x0000, 0x0000, 0x0000, 0x0000, 0x0061, 0x6564,
+	0x0064, 0x6564, 0x0000, 0x6469, 0x6969, 0x6400, 0x0064, 0x6564,
+	0x0063, 0x6568, 0x6200, 0x0064, 0x6864, 0x0000, 0x6268, 0x6563,
+	0x0000, 0x6567, 0x6963, 0x0064, 0x6764, 0x0063, 0x6967, 0x6500,
+	0x0000, 0x6266, 0x6769, 0x6a68, 0x6768, 0x6a69, 0x6766, 0x6200,
+	0x0000, 0x0062, 0x6566, 0x6666, 0x6666, 0x6666, 0x6562, 0x0000,
+	0x0000, 0x0000, 0x0062, 0x6364, 0x6664, 0x6362, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0062, 0x6662, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0061, 0x6661, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x6500, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x6400, 0x0000, 0x0000, 0x0000
+};
+
+/* this is a 16 bit, non-reflected CRC using the polynomial 0x1021 and the
+ * initial and final xor values shown below; in other words, the CCITT standard
+ * CRC used by XMODEM */
+enum{
+	Ncrc0 = 0xffff,
+	Nxor = 0
+};
+static u16int crct[] ={
+	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
+	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
+	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
+	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
+	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
+	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
+	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
+	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
+	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
+	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
+	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
+	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
+	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
+	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
+	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
+	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
+	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
+	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
+	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
+	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
+	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
+	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
+	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
+	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
+	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
+	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
+	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
+	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
+	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
+	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
+	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
+	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
+};
+
+static int notid1;
+static int loadsize;
+static uchar *loadbuf;
+static mem_user_t *loadcache;
+static FILE *demof;
+static vlong demoofs;
+
+#define	GBIT32(p)	((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24))
+#define	PBIT32(p,v)	(p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24
+
+void
+crc(u8int v)
+{
+	crcn = crcn << 8 ^ crct[crcn >> 8 ^ v];
+}
+
+void
+initcrc(void)
+{
+	crcn = Ncrc0;
+}
+
+char *
+ext(char *f, char *e)
+{
+	return strrchr(f, '.') > strrchr(f, '/') ? "" : e;
+}
+
+void
+radix(char *f, char *d)
+{
+	char *s, *e;
+
+	s = strrchr(f, '/');
+	e = strrchr(f, '.');
+	if(s == nil)
+		s = f;
+	s++;
+	if(e - s < 1)
+		strcpy(d, "?model?");
+	else{
+		strncpy(d, s, e - s);
+		d[e - s] = 0;
+	}
+}
+
+static void
+path(void)
+{
+	Paklist *pl;
+
+	for(pl=pkl; pl!=nil; pl=pl->pl)
+		if(pl->p)
+			Con_Printf(va("%s (%zd files)\n", pl->p->f, pl->p->e - pl->p->l));
+		else
+			Con_Printf("%s\n", pl->fname);
+}
+
+static long
+eread(FILE *f, void *u, long n)
+{
+	if(fread(u, 1, n, f) != n)
+		fatal("eread: short read");
+	return n;
+}
+
+static u8int
+get8(FILE *f)
+{
+	u8int v;
+
+	eread(f, &v, 1);
+	return v;
+}
+
+static u16int
+get16(FILE *f)
+{
+	u16int v;
+
+	v = get8(f);
+	return v | get8(f) << 8;
+}
+
+static u32int
+get32(FILE *f)
+{
+	u32int v;
+
+	v = get16(f);
+	return v | get16(f) << 16;
+}
+
+static float
+getfl(FILE *f)
+{
+	union{
+		float v;
+		u32int u;
+	} u;
+
+	u.u = get32(f);
+	return u.v;
+}
+
+static u16int
+get16b(FILE *f)
+{
+	u16int v;
+
+	v = get8(f);
+	return v << 8 | get8(f);
+}
+
+static void
+ewrite(FILE *f, void *u, long n)
+{
+	if(fwrite(u, 1, n, f) != n)
+		fatal("eread: short write");
+}
+
+static void
+put32(FILE *f, u32int v)
+{
+	uchar u[4];
+
+	PBIT32(u, v);
+	ewrite(f, u, 4);
+}
+
+static void
+putfl(FILE *f, float v)
+{
+	union{
+		float v;
+		u32int u;
+	} w;
+
+	w.v = v;
+	put32(f, w.u);
+}
+
+static vlong
+bsize(FILE *f)
+{
+	struct stat st;
+
+	if(fstat(fileno(f), &st) != 0)
+		fatal("fstat");
+	return st.st_size;
+}
+
+static int
+mkpath(char *path)
+{
+	char *d;
+
+	d = path;
+	if(d == nil || *d == 0)
+		return -1;
+	if(*d == '/')
+		d++;
+	while(*d != 0){
+		if(*d == '/'){
+			*d = 0;
+			if(mkdir(path, 0770) < 0)
+				return -1;
+			*d = '/';
+		}
+		d++;
+	}
+	return mkdir(path, 0770);
+}
+
+static void
+closelmp(FILE *f)
+{
+	Paklist *pl;
+
+	for(pl=pkl; pl!=nil; pl=pl->pl)
+		if(pl->p && pl->p->f == f)
+			return;
+	fclose(f);
+}
+
+static FILE *
+openlmp(char *fname, int *len)
+{
+	char d[Nfspath+1];
+	FILE *f;
+	Paklist *pl;
+	Pak *p;
+	Lump *l;
+
+	for(pl=pkl; pl != nil; pl=pl->pl){
+		if(pl->p != nil){
+			p = pl->p;
+			l = p->l;
+			while(l < p->e){
+				if(strcmp(l->fname, fname) == 0){
+					fseek(p->f, l->ofs, SEEK_SET);
+					if(len != nil)
+						*len = l->len;
+					return p->f;
+				}
+				l++;
+			}
+			continue;
+		}
+		snprint(d, sizeof d, "%s/%s", pl->fname, fname);
+		if(f = fopen(d, "rb"), f == nil)
+			continue;
+		if(len != nil)
+			*len = bsize(f);
+		return f;
+	}
+	//fprintf(stderr, "openlmp %s: not found\n", fname);
+	return nil;
+}
+
+static uchar *
+loadlmp(char *fname, int mth, int *n)
+{
+	int m;
+	char r[32];
+	uchar *buf;
+	FILE *f;
+
+	f = openlmp(fname, &m);
+	if(f == nil)
+		return nil;
+	radix(fname, r);
+	buf = nil;
+	switch(mth){
+	case Fhunk: buf = Hunk_Alloc(m + 1); break;
+	case Fcache: buf = Cache_Alloc(loadcache, m + 1); break;
+	case Fstack: buf = m + 1 <= loadsize ? loadbuf : Hunk_TempAlloc(m + 1); break;
+	}
+	if(buf == nil)
+		fatal("loadlmp %s %d: memory allocation failed", fname, m + 1);
+	buf[m] = 0;
+	eread(f, buf, m);
+	closelmp(f);
+	if(n != nil)
+		*n = m;
+	return buf;
+}
+
+void *
+loadhunklmp(char *f, int *n)
+{
+	return loadlmp(f, Fhunk, n);
+}
+
+void *
+loadcachelmp(char *f, mem_user_t *c)
+{
+	loadcache = c;
+	loadlmp(f, Fcache, nil);
+	return c->data;
+}
+
+void *
+loadstklmp(char *f, void *buf, int nbuf, int *n)
+{
+	loadbuf = buf;
+	loadsize = nbuf;
+	return loadlmp(f, Fstack, n);
+}
+
+void
+loadpoints(void)
+{
+	int i, n, nv;
+	FILE *f;
+	vec3_t v3;
+	vec_t *v;
+	particle_t *p;
+
+	f = openlmp(va("maps/%s.pts", sv.name), &n);
+	if(f == nil){
+		Con_Printf(va("loadpoints failed\n"));
+		return;
+	}
+	nv = 0;
+	for(;;){
+		if(n < 3*4+3)
+			break;
+		for(i=0, v=v3; i<3; i++){
+			*v++ = getfl(f);
+			fseek(f, 1, SEEK_CUR);
+		}
+		n -= 3*4+3;
+		nv++;
+		if(free_particles == nil){
+			Con_Printf("loadpoints: insufficient free particles\n");
+			break;
+		}
+		p = free_particles;
+		free_particles = p->next;
+		p->next = active_particles;
+		active_particles = p;
+		p->die = Q_MAXFLOAT;
+		p->color = -nv & 15;
+		p->type = pt_static;
+		VectorCopy(vec3_origin, p->vel);
+		VectorCopy(v3, p->org);
+	}
+	closelmp(f);
+	Con_Printf("loadpoints: %d points read\n", nv);
+}
+
+static void
+dumpcvars(FILE *f)
+{
+	cvar_t *c;
+
+	for(c=cvar_vars; c!=nil; c=c->next)
+		if(c->archive)
+			if(fprintf(f, "%s \"%s\"\n", c->name, c->string) < 0)
+				fatal("dumpcvars");
+}
+
+static void
+dumpkeys(FILE *f)
+{
+	char **k;
+
+	for(k=keybindings; k<keybindings+256; k++)
+		if(*k != nil && **k != 0)
+			fprintf(f, "bind \"%s\" \"%s\"\n",
+				Key_KeynumToString(k-keybindings), *k);
+}
+
+void
+dumpcfg(void)
+{
+	FILE *f;
+
+	if(!host_initialized)
+		return;
+	f = fopen(va("%s/config.cfg", fsdir), "wb");
+	if(f == nil){
+		Con_DPrintf("dumpcfg failed\n");
+		return;
+	}
+	dumpkeys(f);
+	dumpcvars(f);
+	fclose(f);
+}
+
+void
+savnames(void)
+{
+	int n, *canld;
+	char (*e)[Nsavcm], (*s)[Nsavcm], *p;
+	char tmp[8192];
+	FILE *f;
+
+	s = savs;
+	canld = savcanld;
+	for(n=0, e=savs+Nsav; s<e; n++, s++, canld++){
+		*canld = 0;
+		memset(*s, 0, sizeof *s);
+		strcpy(*s, "--- UNUSED SLOT ---");
+		f = fopen(va("%s/s%d.sav", fsdir, n), "rb");
+		if(f == nil){
+			Con_DPrintf("savnames failed\n");
+			continue;
+		}
+		if((p = fgets(tmp, sizeof(tmp), f), p == nil)	/* discard version */
+		|| (p = fgets(tmp, sizeof(tmp), f), p == nil)){
+			Con_DPrintf("savnames: short read\n");
+			continue;
+		}
+		strncpy(*s, p, sizeof(*s)-1);
+		for(p=*s; p<*(s+1); p++)
+			if(*p == '_')
+				*p = ' ';
+		*canld = 1;
+		fclose(f);
+	}
+}
+
+static void
+dumpedicts(FILE *f, edict_t *ed)
+{
+	int *vp, *ve;
+	char *s;
+	uchar *ev;
+	ddef_t *d, *de;
+	eval_t *v;
+
+	fprintf(f, "{\n");
+	if(ed->free)
+		goto end;
+	ev = (uchar *)&ed->v;
+	de = pr_fielddefs + progs->numfielddefs;
+	for(d=pr_fielddefs+1; d<de; d++){
+		s = PR_Str(d->s_name);
+		if(s[strlen(s)-2] == '_')
+			continue;
+		/* TODO: pragma pack hazard */
+		vp = (int *)(ev + d->ofs * 4);
+		ve = vp + type_size[d->type & ~DEF_SAVEGLOBAL];
+		v = (eval_t *)vp;
+		for(; vp<ve; vp++)
+			if(*vp != 0)
+				break;
+		if(vp == ve)
+			continue;
+		fprintf(f, "\"%s\" ", s);
+		fprintf(f, "\"%s\"\n", PR_UglyValueString(d->type, v));
+	}
+end:
+	fprintf(f, "}\n");
+}
+
+static void
+dumpdefs(FILE *f)
+{
+	ushort t;
+	ddef_t *d, *de;
+
+	fprintf(f, "{\n");
+	de = pr_globaldefs + progs->numglobaldefs;
+	for(d=pr_globaldefs; d<de; d++){
+		t = d->type;
+		if((t & DEF_SAVEGLOBAL) == 0)
+			continue;
+		t &= ~DEF_SAVEGLOBAL;
+		if(t != ev_string && t != ev_float && t != ev_entity)
+			continue;
+		fprintf(f, "\"%s\" \"%s\"\n", PR_Str(d->s_name),
+			PR_UglyValueString(t, (eval_t *)&pr_globals[d->ofs]));
+	}
+	fprintf(f, "}\n");
+}
+
+int
+dumpsav(char *fname, char *cm)
+{
+	int i;
+	char **s, **e;
+	float *fs, *fe;
+	FILE *f;
+
+	f = fopen(fname, "wb");
+	if(f == nil)
+		return -1;
+	fprintf(f, "%d\n%s\n", Nsavver, cm);
+	fs = svs.clients->spawn_parms;
+	fe = fs + nelem(svs.clients->spawn_parms);
+	while(fs < fe)
+		fprintf(f, "%f\n", *fs++);
+	fprintf(f, "%d\n%s\n%f\n", current_skill, sv.name, sv.time);
+	s = sv.lightstyles;
+	e = s + nelem(sv.lightstyles);
+	while(s < e){
+		fprintf(f, "%s\n", *s != nil ? *s : "m");
+		s++;
+	}
+	dumpdefs(f);
+	for(i=0; i<sv.num_edicts; i++)
+		dumpedicts(f, EDICT_NUM(i));
+	fclose(f);
+	return 0;
+}
+
+static void
+loadedicts(FILE *f)
+{
+	int ent, c;
+	char sb[32768], *s;
+	edict_t *ed;
+
+	ent = -1;
+	c = 0;
+	do{
+		for(s=sb; s<sb+sizeof(sb)-1; s++){
+			c = fgetc(f);
+			if(c == EOF || c == 0)
+				break;
+			*s = c;
+			if(c == '}'){
+				s++;
+				break;
+			}
+		}
+		if(s == sb + sizeof(sb) - 1)
+			fatal("loadgame: buffer overflow");
+		*s = 0;
+		s = COM_Parse(sb);
+		if(com_token[0] == 0)
+			break;
+		if(strcmp(com_token, "{") != 0)
+			fatal("loadgame: missing opening brace");
+		if(ent == -1)
+			ED_ParseGlobals(s);
+		else{
+			ed = EDICT_NUM(ent);
+			/* TODO: pragma pack hazard */
+			memset(&ed->v, 0, progs->entityfields * 4);
+			ed->free = 0;
+			ED_ParseEdict(s, ed);
+			if(!ed->free)
+				SV_LinkEdict(ed, 0);
+		}
+		ent++;
+	}while(c != EOF);
+	sv.num_edicts = ent;
+}
+
+static int
+loadparms(FILE *f, char *fname)
+{
+	int r;
+	float sp[Nparms], *p;
+	char *s, **lp;
+	char tmp[8192];
+
+	r = -1;
+	p = sp;
+	while(p < sp + nelem(sp)){
+		if(s = fgets(tmp, sizeof(tmp), f), s == nil)
+			goto exit;
+		*p++ = (float)strtod(s, nil);
+	}
+	if(s = fgets(tmp, sizeof(tmp), f), s == nil)
+		goto exit;
+	current_skill = (int)(strtod(s, nil) + 0.1);
+	setcvarv("skill", (float)current_skill);
+	if(s = fgets(tmp, sizeof(tmp), f), s == nil)
+		goto exit;
+	CL_Disconnect_f();
+	SV_SpawnServer(s);
+	if(!sv.active)
+		goto exit;
+	sv.paused = 1;
+	sv.loadgame = 1;
+	if(s = fgets(tmp, sizeof(tmp), f), s == nil)
+		goto exit;
+	sv.time = strtod(s, nil);
+	lp = sv.lightstyles;
+	while(lp < sv.lightstyles + nelem(sv.lightstyles)){
+		if(s = fgets(tmp, sizeof(tmp), f), s == nil)
+			goto exit;
+		*lp = Hunk_Alloc(strlen(s)+1);
+		strcpy(*lp++, s);
+	}
+	r = 0;
+	loadedicts(f);
+	memcpy(svs.clients->spawn_parms, sp, sizeof sp);
+exit:
+	return r;
+}
+
+int
+loadsav(char *fname)
+{
+	int n, r;
+	char *s;
+	FILE *f;
+	char tmp[8192];
+
+	f = fopen(fname, "rb");
+	if(f == nil)
+		return -1;
+	r = -1;
+	if(s = fgets(tmp, sizeof(tmp), f), s == nil)
+		goto exit;
+	n = strtol(s, nil, 10);
+	if(n != Nsavver){
+		werrstr("invalid version %d", n);
+		goto exit;
+	}
+	s = fgets(tmp, sizeof(tmp), f);
+	r = loadparms(f, fname);
+exit:
+	fclose(f);
+	return r;
+}
+
+void
+closedm(void)
+{
+	if(demof == nil)
+		return;
+	closelmp(demof);
+	demof = nil;
+}
+
+void
+writedm(void)
+{
+	int i;
+
+	put32(demof, net_message.cursize);
+	for(i=0; i<3; i++)
+		putfl(demof, cl.viewangles[i]);
+	ewrite(demof, net_message.data, net_message.cursize);
+}
+
+int
+readdm(void)
+{
+	int n;
+	vec_t *f;
+
+	fseek(demof, demoofs, SEEK_SET);
+	net_message.cursize = get32(demof);
+	VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
+	for(n=0, f=cl.mviewangles[0]; n<3; n++)
+		*f++ = getfl(demof);
+	if(net_message.cursize > NET_MAXMESSAGE)
+		fatal("readdm: invalid message size %d\n", net_message.cursize);
+	n = fread(net_message.data, 1, net_message.cursize, demof);
+	demoofs = ftell(demof);
+	if(n < 0)
+		Con_DPrintf("readdm: bad read\n");
+	if(n != net_message.cursize){
+		Con_DPrintf("readdm: short read\n");
+		n = -1;
+	}
+	return n;
+}
+
+int
+loaddm(char *fname)
+{
+	int n;
+	char *s, tmp[8192];
+
+	demof = openlmp(fname, &n);
+	if(demof == nil)
+		return -1;
+	s = fgets(tmp, sizeof(tmp), demof);
+	n = strlen(s) - 1;
+	if(s == nil || n < 0 || n > 11){
+		Con_DPrintf("loaddm: invalid trk field\n");
+		closelmp(demof);
+		return -1;
+	}
+	demoofs = ftell(demof);
+	s[n] = 0;
+	cls.forcetrack =  strtol(s, nil, 10);
+	return 0;
+}
+
+int
+opendm(char *f, int trk)
+{
+	char s[16];
+
+	demof = fopen(f, "wb");
+	if(demof == nil)
+		return -1;
+	sprint(s, "%d\n", trk);
+	ewrite(demof, s, strlen(s));
+	return 0;
+}
+
+static Pak *
+pak(char *fname)
+{
+	int n, ofs, len, nlmp;
+	uchar u[8];
+	FILE *f;
+	Lump *l;
+	Pak *p;
+
+	f = fopen(fname, "rb");
+	if(f == nil)
+		return nil;
+	memset(u, 0, sizeof u);
+	eread(f, u, 4);
+	if(memcmp(u, "PACK", 4) != 0)
+		fatal("pak %s: invalid pak file", fname);
+	ofs = get32(f);
+	len = get32(f);
+	nlmp = len / Npaksz;
+	if(nlmp > Npaklmp)
+		fatal("pak %s: invalid lump number %d", fname, nlmp);
+	if(nlmp != Npak0lmp)
+		notid1 = 1;
+	l = Hunk_Alloc(nlmp * sizeof *l);
+	p = Hunk_Alloc(sizeof *p);
+	snprint(p->fname, sizeof(p->fname), "%s", fname);
+	p->f = f;
+	p->l = l;
+	p->e = l + nlmp;
+	fseek(f, ofs, SEEK_SET);
+	initcrc();
+	while(l < p->e){
+		eread(f, l->fname, 56);
+		for(n=0; n<56; n++)
+			crc(l->fname[n]);
+		eread(f, u, 8);
+		for(n=0; n<8; n++)
+			crc(u[n]);
+		l->ofs = GBIT32(u);
+		l->len = GBIT32(u+4);
+		l++;
+	}
+	if(crcn != Npak0crc)
+		notid1 = 1;
+	return p;
+}
+
+static void
+pakdir(char *d)
+{
+	int n;
+	char f[Nfspath];
+	Paklist *pl;
+	Pak *p;
+
+	strncpy(fsdir, d, sizeof(fsdir)-1);
+	pl = Hunk_Alloc(sizeof *pl);
+	strncpy(pl->fname, d, sizeof(pl->fname)-1);
+	pl->pl = pkl;
+	pkl = pl;
+	for(n=0; ; n++){
+		snprint(f, sizeof f, "%s/pak%d.pak", d, n);
+		p = pak(f);
+		if(p == nil){
+			Con_DPrintf("pakdir: %r\n");
+			break;
+		}
+		pl = Hunk_Alloc(sizeof *pl);
+		pl->p = p;
+		pl->pl = pkl;
+		pkl = pl;
+	}
+}
+
+static void
+initns(void)
+{
+	char *home;
+
+	pakdir("/usr/games/quake/id1");
+	if(game != nil){
+		if(strcmp(game, "rogue") == 0){
+			rogue = 1;
+			standard_quake = 0;
+		}else if(strcmp(game, "hipnotic") == 0){
+			hipnotic = 1;
+			standard_quake = 0;
+		}else
+			notid1 = 1;
+		pakdir(va("/usr/games/quake/%s", game));
+	}
+	if((home = getenv("HOME")) != nil){
+		pakdir(va("%s/.quake/id1", home));
+		if(game != nil)
+			pakdir(va("%s/.quake/%s", home, game));
+		mkpath(fsdir);
+	}
+}
+
+static void
+chkreg(void)
+{
+	u16int *p;
+	FILE *f;
+
+	Cvar_RegisterVariable(&registered);
+	f = openlmp("gfx/pop.lmp", nil);
+	if(f == nil){
+		Con_DPrintf("chkreg: shareware version\n");
+		if(notid1)
+			fatal("chkreg: phase error");
+		return;
+	}
+	p = pop;
+	while(p < pop + nelem(pop))
+		if(*p++ != get16b(f))
+			fatal("chkreg: corrupted pop lump");
+	closelmp(f);
+	setcvar("registered", "1");
+	Con_DPrintf("chkreg: registered version\n");
+}
+
+/* TODO: nuke these from orbit */
+static short
+ShortSwap(short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	return (b1<<8) + b2;
+}
+static short
+ShortNoSwap(short l)
+{
+	return l;
+}
+static int
+LongSwap(int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+static int
+LongNoSwap(int l)
+{
+	return l;
+}
+static float
+FloatSwap(float f)
+{
+	union{
+		float   f;
+		byte    b[4];
+	} dat1, dat2;
+
+	dat1.f = f;
+	dat2.b[0] = dat1.b[3];
+	dat2.b[1] = dat1.b[2];
+	dat2.b[2] = dat1.b[1];
+	dat2.b[3] = dat1.b[0];
+	return dat2.f;
+}
+static float
+FloatNoSwap(float f)
+{
+	return f;
+}
+
+void
+initfs(void)
+{
+	byte swaptest[2] = {1,0};
+
+	if(*(short *)swaptest == 1)
+	{
+		BigShort = ShortSwap;
+		LittleShort = ShortNoSwap;
+		BigLong = LongSwap;
+		LittleLong = LongNoSwap;
+		BigFloat = FloatSwap;
+		LittleFloat = FloatNoSwap;
+	}else{
+		BigShort = ShortNoSwap;
+		LittleShort = ShortSwap;
+		BigLong = LongNoSwap;
+		LittleLong = LongSwap;
+		BigFloat = FloatNoSwap;
+		LittleFloat = FloatSwap;
+	}
+	initns();
+	chkreg();
+	Cmd_AddCommand("path", path);
+}
--- /dev/null
+++ b/unix/in.c
@@ -1,0 +1,168 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+#include <SDL.h>
+
+/* vid.c */
+extern int resized;
+
+static cvar_t m_windowed = {"m_windowed", "1", true};
+static cvar_t m_filter = {"m_filter", "0", true};
+static int mouseon, oldmwin;
+static float olddx, olddy;
+static int mΔx, mΔy, oldmb;
+
+void
+conscmd(void)
+{
+}
+
+void
+Sys_SendKeyEvents(void)
+{
+	SDL_Event event;
+	int key;
+
+	if(cls.state == ca_dedicated)
+		return;
+	if(oldmwin != (int)m_windowed.value){
+		oldmwin = (int)m_windowed.value;
+		IN_Grabm(oldmwin);
+	}
+
+	while(SDL_PollEvent(&event)){
+		switch(event.type){
+		case SDL_QUIT:
+			Cbuf_AddText("menu_quit\n");
+			break;
+		case SDL_WINDOWEVENT:
+			if(event.window.event == SDL_WINDOWEVENT_RESIZED)
+				resized = 1;
+			break;
+		case SDL_MOUSEMOTION:
+			if(mouseon){
+				mΔx += event.motion.xrel;
+				mΔy += event.motion.yrel;
+			}
+			break;
+		case SDL_KEYDOWN:
+		case SDL_KEYUP:
+			switch(key = event.key.keysym.sym){
+			case SDLK_BACKQUOTE: key = '~'; break;
+			case SDLK_DELETE: key = K_DEL; break;
+			case SDLK_BACKSPACE: key = K_BACKSPACE; break;
+			case SDLK_F1: key = K_F1; break;
+			case SDLK_F2: key = K_F2; break;
+			case SDLK_F3: key = K_F3; break;
+			case SDLK_F4: key = K_F4; break;
+			case SDLK_F5: key = K_F5; break;
+			case SDLK_F6: key = K_F6; break;
+			case SDLK_F7: key = K_F7; break;
+			case SDLK_F8: key = K_F8; break;
+			case SDLK_F9: key = K_F9; break;
+			case SDLK_F10: key = K_F10; break;
+			case SDLK_F11: key = K_F11; break;
+			case SDLK_F12: key = K_F12; break;
+			case SDLK_PAUSE: key = K_PAUSE; break;
+			case SDLK_UP: key = K_UPARROW; break;
+			case SDLK_DOWN: key = K_DOWNARROW; break;
+			case SDLK_RIGHT: key = K_RIGHTARROW; break;
+			case SDLK_LEFT: key = K_LEFTARROW; break;
+			case SDLK_RSHIFT:
+			case SDLK_LSHIFT: key = K_SHIFT; break;
+			case SDLK_RCTRL:
+			case SDLK_LCTRL: key = K_CTRL; break;
+			case SDLK_RALT:
+			case SDLK_LALT: key = K_ALT; break;
+			default:
+				if(key >= 128)
+					key = 0;
+				break;
+			}
+			if(key > 0)
+				Key_Event(key, event.key.state);
+			break;
+		}
+	}
+}
+
+void
+IN_Commands(void)
+{
+	int b, i, k, r;
+
+	if(!mouseon || cls.state == ca_dedicated)
+		return;
+	b = SDL_GetMouseState(nil, nil);
+	b = (b & 0x19) | ((b & 2) << 1) | ((b & 4) >> 1);
+	for(i=0, k=K_MOUSE1; i<5; i++, k++){
+		if(i == 3)
+			k = K_MWHEELUP;
+		r = b & 1<<i;
+		if(r ^ (oldmb & 1<<i))
+			Key_Event(k, r);
+	}
+	oldmb = b & 7;
+}
+
+void
+IN_Move(usercmd_t *cmd)
+{
+	float dx, dy;
+
+	if(!mouseon)
+		return;
+
+	dx = mΔx;
+	dy = mΔy;
+	mΔx = 0;
+	mΔy = 0;
+	if(m_filter.value){
+		dx = (dx + olddx) * 0.5;
+		dy = (dy + olddy) * 0.5;
+	}
+	olddx = dx;
+	olddy = dy;
+	dx *= sensitivity.value;
+	dy *= sensitivity.value;
+	if(in_strafe.state & 1 || (lookstrafe.value && in_mlook.state & 1))
+		cmd->sidemove += m_side.value * dx;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * dx;
+	if(in_mlook.state & 1)
+		V_StopPitchDrift();
+	if(in_mlook.state & 1 && ~in_strafe.state & 1){
+		cl.viewangles[PITCH] += m_pitch.value * dy;
+		if(cl.viewangles[PITCH] > 80)
+			cl.viewangles[PITCH] = 80;
+		if(cl.viewangles[PITCH] < -70)
+			cl.viewangles[PITCH] = -70;
+	}else{
+		if(in_strafe.state & 1 && noclip_anglehack)
+			cmd->upmove -= m_forward.value * dy;
+		else
+			cmd->forwardmove -= m_forward.value * dy;
+	}
+}
+
+void
+IN_Grabm(int on)
+{
+	mouseon = on;
+	SDL_SetRelativeMouseMode(on ? SDL_TRUE : SDL_FALSE);
+}
+
+void
+IN_Shutdown(void)
+{
+	IN_Grabm(0);
+}
+
+void
+IN_Init(void)
+{
+	Cvar_RegisterVariable(&m_windowed);
+	Cvar_RegisterVariable(&m_filter);
+}
--- /dev/null
+++ b/unix/net_udp.c
@@ -1,0 +1,363 @@
+#include <u.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+
+extern cvar_t hostname;
+
+static int net_acceptsocket = -1; // socket for fielding new connections
+static int net_controlsocket;
+static int net_broadcastsocket = 0;
+static Addr broadcastaddr;
+
+static unsigned long myAddr;
+Addr myip;
+
+static int UDP_OpenSocket (int port);
+static int UDP_GetSocketAddr (int socket, Addr *addr);
+static int UDP_CloseSocket (int socket);
+
+//=============================================================================
+
+int UDP_Init (void)
+{
+	struct hostent *local;
+	char buff[MAXHOSTNAMELEN];
+
+	// determine my name & address
+	gethostname(buff, MAXHOSTNAMELEN);
+	local = gethostbyname(buff);
+	myAddr = *(int *)local->h_addr_list[0];
+
+	// if the quake hostname isn't set, set it to the machine name
+	if (strcmp(hostname.string, "UNNAMED") == 0)
+	{
+		buff[15] = 0;
+		setcvar ("hostname", buff);
+	}
+
+	if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
+		Host_Error("UDP_Init: Unable to open control socket\n");
+
+	((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
+	((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
+	((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(Udpport);
+
+	UDP_GetSocketAddr (net_controlsocket, &myip);
+
+	return net_controlsocket;
+}
+
+//=============================================================================
+
+void UDP_Shutdown (void)
+{
+	UDP_Listen (false);
+	UDP_CloseSocket (net_controlsocket);
+}
+
+//=============================================================================
+
+void UDP_Listen (qboolean state)
+{
+	// enable listening
+	if (state)
+	{
+		if (net_acceptsocket != -1)
+			return;
+		if ((net_acceptsocket = UDP_OpenSocket (Udpport)) == -1)
+			Host_Error ("UDP_Listen: Unable to open accept socket\n");
+		return;
+	}
+
+	// disable listening
+	if (net_acceptsocket == -1)
+		return;
+	UDP_CloseSocket (net_acceptsocket);
+	net_acceptsocket = -1;
+}
+
+//=============================================================================
+
+static int UDP_OpenSocket (int port)
+{
+	int newsocket;
+	struct sockaddr_in address;
+
+	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+		return -1;
+
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = INADDR_ANY;
+	address.sin_port = htons(port);
+	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
+		goto ErrorReturn;
+
+	return newsocket;
+
+ErrorReturn:
+	close (newsocket);
+	return -1;
+}
+
+//=============================================================================
+
+static int UDP_CloseSocket (int socket)
+{
+	if (socket == net_broadcastsocket)
+		net_broadcastsocket = 0;
+	return close (socket);
+}
+
+//=============================================================================
+/*
+============
+PartialIPAddress
+
+this lets you type only as much of the net address as required, using
+the local network components to fill in the rest
+============
+*/
+static int PartialIPAddress (char *in, Addr *hostaddr)
+{
+	char buff[256];
+	char *b;
+	int addr;
+	int num;
+	int mask;
+	int run;
+	int port;
+
+	buff[0] = '.';
+	b = buff;
+	strcpy(buff+1, in);
+	if (buff[1] == '.')
+		b++;
+
+	addr = 0;
+	mask=-1;
+	while (*b == '.')
+	{
+		b++;
+		num = 0;
+		run = 0;
+		while (!( *b < '0' || *b > '9'))
+		{
+		  num = num*10 + *b++ - '0';
+		  if (++run > 3)
+		  	return -1;
+		}
+		if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
+			return -1;
+		if (num < 0 || num > 255)
+			return -1;
+		mask<<=8;
+		addr = (addr<<8) + num;
+	}
+
+	if (*b++ == ':')
+		port = strtol(b, NULL, 0);
+	else
+		port = Udpport;
+
+	((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
+	((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
+
+	return 0;
+}
+//=============================================================================
+
+int UDP_Connect (Addr *addr)
+{
+	return 0;
+}
+
+//=============================================================================
+
+int UDP_CheckNewConnections (void)
+{
+	unsigned long available;
+
+	if (net_acceptsocket == -1)
+		return -1;
+
+	if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
+		Host_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
+	if (available)
+		return net_acceptsocket;
+	return -1;
+}
+
+//=============================================================================
+
+int UDP_Read (int socket, uint8_t *buf, int len, Addr *addr)
+{
+	socklen_t addrlen = sizeof (Addr);
+	int ret;
+
+	ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
+	if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
+		return 0;
+	return ret;
+}
+
+//=============================================================================
+
+int UDP_MakeSocketBroadcastCapable (int socket)
+{
+	int i = 1;
+
+	// make this socket broadcast capable
+	if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
+		return -1;
+	net_broadcastsocket = socket;
+
+	return 0;
+}
+
+//=============================================================================
+
+static int UDP_Write (int socket, uint8_t *buf, int len, Addr *addr)
+{
+	int ret;
+
+	ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(Addr));
+	if (ret == -1 && errno == EWOULDBLOCK)
+		return 0;
+	return ret;
+}
+
+//=============================================================================
+
+int UDP_Broadcast (int socket, uint8_t *buf, int len)
+{
+	int ret;
+
+	if (socket != net_broadcastsocket)
+	{
+		if (net_broadcastsocket != 0)
+			Host_Error("Attempted to use multiple broadcasts sockets\n");
+		ret = UDP_MakeSocketBroadcastCapable (socket);
+		if (ret == -1)
+		{
+			Con_Printf("Unable to make socket broadcast capable\n");
+			return ret;
+		}
+	}
+
+	return UDP_Write (socket, buf, len, &broadcastaddr);
+}
+
+//=============================================================================
+
+char *UDP_AddrToString (Addr *addr)
+{
+	static char buffer[22];
+	int haddr;
+
+	haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
+	sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
+	return buffer;
+}
+
+//=============================================================================
+
+int UDP_StringToAddr (char *string, Addr *addr)
+{
+	int ha1, ha2, ha3, ha4, hp;
+	int ipaddr;
+
+	sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
+	ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
+
+	((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
+	((struct sockaddr_in *)addr)->sin_port = htons(hp);
+	return 0;
+}
+
+//=============================================================================
+
+static int UDP_GetSocketAddr (int socket, Addr *addr)
+{
+	socklen_t addrlen = sizeof(Addr);
+	unsigned int a;
+
+	memset(addr, 0, sizeof(Addr));
+	getsockname(socket, (struct sockaddr *)addr, &addrlen);
+	a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+	if (a == 0 || a == inet_addr("127.0.0.1"))
+		((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
+
+	return 0;
+}
+
+//=============================================================================
+
+int UDP_GetNameFromAddr (Addr *addr, char *name)
+{
+	struct hostent *hostentry;
+
+	hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
+	if (hostentry)
+	{
+		strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
+		return 0;
+	}
+
+	strcpy (name, UDP_AddrToString (addr));
+	return 0;
+}
+
+//=============================================================================
+
+int UDP_GetAddrFromName(char *name, Addr *addr)
+{
+	struct hostent *hostentry;
+
+	if (name[0] >= '0' && name[0] <= '9')
+		return PartialIPAddress (name, addr);
+
+	hostentry = gethostbyname (name);
+	if (!hostentry)
+		return -1;
+
+	((struct sockaddr_in *)addr)->sin_port = htons(Udpport);
+	((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
+
+	return 0;
+}
+
+//=============================================================================
+
+int UDP_AddrCompare (Addr *addr1, Addr *addr2)
+{
+	if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
+		return -1;
+
+	if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
+		return 1;
+
+	return 0;
+}
+
+//=============================================================================
+
+ushort UDP_GetSocketPort (Addr *addr)
+{
+	return ntohs(((struct sockaddr_in *)addr)->sin_port);
+}
+
+void UDP_SetSocketPort (Addr *addr, ushort port)
+{
+	((struct sockaddr_in *)addr)->sin_port = htons(port);
+}
+
+//=============================================================================
--- /dev/null
+++ b/unix/qk1.c
@@ -1,0 +1,102 @@
+#include <u.h>
+#include <time.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+
+char *game;
+int debug;
+
+void
+fatal(char *fmt, ...)
+{
+	va_list arg;
+
+	va_start(arg, fmt);
+	vfprintf(stderr, fmt, arg);
+	va_end(arg);
+	Host_Shutdown();
+	exit(1);
+}
+
+void *
+emalloc(ulong n)
+{
+	void *p;
+
+	if(p = calloc(1, n), p == nil)
+		fatal("emalloc");
+	setmalloctag(p, getcallerpc(&n));
+	return p;
+}
+
+uvlong
+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;
+/*
+	ARGBEGIN{
+	case 'D':
+		debug = 1;
+		break;
+	case 'd':
+		dedicated = 1;
+		break;
+	case 'g':
+		game = EARGF(usage());
+		break;
+	case 'x':
+		netmtpt = EARGF(usage());
+		break;
+	default: usage();
+	}ARGEND
+*/
+
+	game = "ad";
+	srand(getpid());
+	Host_Init(argc, argv);
+	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;
+}
--- /dev/null
+++ b/unix/seprint.c
@@ -1,0 +1,19 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+char *
+seprint(char *buf, char *e, char *fmt, ...)
+{
+	va_list a;
+	int n, m;
+
+	if(e <= buf)
+		return e;
+
+	va_start(a, fmt);
+	m = e-buf-1;
+	n = vsnprintf(buf, m, fmt, a);
+	va_end(a);
+
+	return buf + (n < m ? n : m);
+}
--- /dev/null
+++ b/unix/snd.c
@@ -1,0 +1,65 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+
+cvar_t volume = {"volume", "0.7", 1};
+
+void
+stepsnd(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
+{
+}
+
+void
+stopallsfx(void)
+{
+}
+
+void
+stopsfx(int n, int ch)
+{
+}
+
+void
+startsfx(int entn, int entch, Sfx *sfx, vec3_t zp, float vol, float att)
+{
+}
+
+void
+localsfx(char *s)
+{
+}
+
+void
+staticsfx(Sfx *sfx, vec3_t zp, float vol, float att)
+{
+}
+
+void
+touchsfx(char *s)
+{
+}
+
+Sfx *
+precachesfx(char *s)
+{
+	return nil;
+}
+
+void
+sfxbegin(void)
+{
+}
+
+void
+shutsnd(void)
+{
+}
+
+int
+initsnd(void)
+{
+	Cvar_RegisterVariable(&volume);
+	return -1;
+}
--- /dev/null
+++ b/unix/u.h
@@ -1,0 +1,52 @@
+#pragma once
+
+#include <assert.h>
+#include <fcntl.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+typedef unsigned char uchar;
+typedef long long vlong;
+typedef unsigned long long uvlong;
+typedef uint8_t u8int;
+typedef uint16_t u16int;
+typedef int32_t s32int;
+typedef uint32_t u32int;
+typedef uintptr_t uintptr;
+
+enum {
+	UTFmax = 4,
+	IOUNIT = 32768,
+};
+
+#define OREAD O_RDONLY
+#define OWRITE O_WRONLY
+#define OCEXEC O_CLOEXEC
+#define OTRUNC O_TRUNC
+#define AEXIST F_OK
+
+#define seek lseek
+
+#define nil NULL
+#define USED(x) (void)(x)
+#define nelem(x) (int)(sizeof(x)/sizeof((x)[0]))
+
+#define sprint sprintf
+#define snprint snprintf
+#define vsnprint vsnprintf
+#define cistrcmp strcasecmp
+#define cistrncmp strncasecmp
+#define getcallerpc(x) nil
+#define getmalloctag(p) (USED(p), 0)
+#define setmalloctag(p, t) do{USED(p); USED(t);}while(0)
+#define werrstr(fmt, ...) do{}while(0)
+
+char *seprint(char *, char *, char *, ...);
--- /dev/null
+++ b/unix/vid.c
@@ -1,0 +1,133 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+#include <SDL.h>
+
+int resized;
+
+static SDL_Renderer *rend;
+static SDL_Texture *fbi;
+static SDL_Window *win;
+static u8int *vidbuffer;
+
+s32int fbpal[256];
+
+void pal2xrgb(int n, s32int *pal, u8int *s, u32int *d);
+
+static void
+resetfb(void)
+{
+	void *surfcache;
+	int hunkvbuf, scachesz;
+
+	/* lower than 320x240 doesn't really make sense,
+	 * but at least this prevents a crash, beyond that
+	 * it's your funeral */
+	SDL_GetWindowSize(win, &vid.width, &vid.height);
+	if(vid.width < 320)
+		vid.width = 320;
+	if(vid.height < 160)
+		vid.height = 160;
+	if(d_pzbuffer != nil){
+		D_FlushCaches();
+		free(d_pzbuffer);
+		d_pzbuffer = nil;
+	}
+
+	// alloc an extra line in case we want to wrap, and allocate the z-buffer
+	hunkvbuf = vid.width * vid.height * sizeof *d_pzbuffer;
+	scachesz = D_SurfaceCacheForRes(vid.width, vid.height);
+	hunkvbuf += scachesz;
+	d_pzbuffer = emalloc(hunkvbuf);
+	surfcache = (byte *)d_pzbuffer + vid.width * vid.height * sizeof *d_pzbuffer;
+	D_InitCaches(surfcache, scachesz);
+
+	vid.rowbytes = vid.width;
+	vid.aspect = (float)vid.height / (float)vid.width * (320.0/240.0);
+	vid.conrowbytes = vid.rowbytes;
+	vid.conwidth = vid.width;
+	vid.conheight = vid.height;
+
+	free(vidbuffer);
+	vidbuffer = emalloc(vid.width*vid.height);
+
+	if(fbi != nil)
+		SDL_DestroyTexture(fbi);
+	fbi = SDL_CreateTexture(rend, SDL_PIXELFORMAT_XRGB8888, SDL_TEXTUREACCESS_STREAMING, vid.width, vid.height);
+	if(fbi == NULL)
+		fatal("SDL_CreateTexture: %s", SDL_GetError());
+	SDL_SetTextureBlendMode(fbi, SDL_BLENDMODE_NONE);
+	SDL_RenderClear(rend);
+
+	vid.buffer = vidbuffer;
+	vid.conbuffer = vid.buffer;
+}
+
+void
+stopfb(void)
+{
+}
+
+void
+flipfb(void)
+{
+	int pitch;
+	void *p;
+
+	if(resized){		/* skip this frame if window resize */
+		stopfb();
+		resized = 0;
+		resetfb();
+		vid.recalc_refdef = 1;	/* force a surface cache flush */
+		Con_CheckResize();
+		Con_Clear_f();
+		return;
+	}
+
+	SDL_LockTexture(fbi, NULL, &p, &pitch);
+	pal2xrgb(vid.width*vid.height, fbpal, vidbuffer, p);
+	SDL_UnlockTexture(fbi);
+	SDL_RenderCopy(rend, fbi, NULL, NULL);
+	SDL_RenderPresent(rend);
+}
+
+void
+setpal(uchar *p)
+{
+	int *fp;
+
+	for(fp=fbpal; fp<fbpal+nelem(fbpal); p+=3, fp++)
+		*fp = p[0] << 16 | p[1] << 8 | p[2];
+
+	initalpha();
+
+	scr_fullupdate = 0;
+}
+
+void
+initfb(void)
+{
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.numpages = 2;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong(*((int *)vid.colormap + 2048));
+
+	if(SDL_Init(SDL_INIT_VIDEO) < 0)
+		fatal("SDL_Init: %s", SDL_GetError());
+	win = SDL_CreateWindow("quake", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_RESIZABLE);
+	if(win == nil)
+		fatal("SDL_CreateWindow: %s", SDL_GetError());
+	if((rend = SDL_CreateRenderer(win, -1, 0)) == NULL)
+		fatal("SDL_CreateRenderer: %s", SDL_GetError());
+	SDL_SetRenderDrawColor(rend, 0, 0, 0, 255);
+	SDL_RenderClear(rend);
+	SDL_RenderPresent(rend);
+	SDL_SetWindowPosition(win, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+	SDL_ShowWindow(win);
+	SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
+
+	resetfb();
+}
--- a/vid.c
+++ b/vid.c
@@ -112,8 +112,6 @@
 	if(resized){		/* skip this frame if window resize */
 		stopfb();
 		resized = 0;
-		if(getwindow(display, Refnone) < 0)
-			sysfatal("getwindow: %r");
 		resetfb();
 		vid.recalc_refdef = 1;	/* force a surface cache flush */
 		Con_CheckResize();
--- a/vid.h
+++ b/vid.h
@@ -19,8 +19,8 @@
 	unsigned short	*colormap16;	// 256 * VID_GRADES size
 	int				fullbright;		// index of first fullbright color
 	unsigned		rowbytes;	// may be > width if displayed in a window
-	unsigned		width;		
-	unsigned		height;
+	int				width;		
+	int				height;
 	float			aspect;		// width / height -- < 0 is taller than wide
 	int				numpages;
 	int				recalc_refdef;	// if true, recalc vid-based stuff
--- a/view.c
+++ b/view.c
@@ -792,25 +792,23 @@
 	VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
 
 // smooth out stair step ups
-if (cl.onground && ent->origin[2] - oldz > 0)
-{
-	float steptime;
-	
-	steptime = cl.time - cl.oldtime;
-	if (steptime < 0)
+	if (cl.onground && ent->origin[2] - oldz > 0){
+		float steptime;
+
+		steptime = cl.time - cl.oldtime;
+		if (steptime < 0)
 //FIXME		I_Error ("steptime < 0");
-		steptime = 0;
+			steptime = 0;
 
-	oldz += steptime * 80;
-	if (oldz > ent->origin[2])
+		oldz += steptime * 80;
+		if (oldz > ent->origin[2])
+			oldz = ent->origin[2];
+		if (ent->origin[2] - oldz > 12)
+			oldz = ent->origin[2] - 12;
+		r_refdef.vieworg[2] += oldz - ent->origin[2];
+		view->origin[2] += oldz - ent->origin[2];
+	}else
 		oldz = ent->origin[2];
-	if (ent->origin[2] - oldz > 12)
-		oldz = ent->origin[2] - 12;
-	r_refdef.vieworg[2] += oldz - ent->origin[2];
-	view->origin[2] += oldz - ent->origin[2];
-}
-else
-	oldz = ent->origin[2];
 
 	if (chase_active.value)
 		Chase_Update ();
--- a/zone.c
+++ b/zone.c
@@ -62,9 +62,9 @@
 {
 	mem_t *m;
 
-	m = mallocz(sizeof(*m) + size, 1);
+	m = calloc(1, sizeof(*m) + size);
 	if(m == nil)
-		sysfatal("Hunk_Alloc: %r");
+		fatal("Hunk_Alloc: %r");
 	m->size = size;
 	m->next = hunk_head;
 	if(hunk_head != nil)
@@ -85,7 +85,7 @@
 	t = getmalloctag(m);
 	n = realloc(m, sizeof(*m) + m->size*2);
 	if(m == nil)
-		sysfatal("Hunk_Double: %r");
+		fatal("Hunk_Double: %r");
 	if(hunk_head == m)
 		hunk_head = n;
 	m = n;
@@ -126,7 +126,7 @@
 	if(size > bufsz){
 		buf = realloc(buf, size);
 		if(buf == nil)
-			sysfatal("Hunk_TempAlloc: %r");
+			fatal("Hunk_TempAlloc: %r");
 		bufsz = size;
 	}
 	memset(buf, 0, size);
@@ -182,9 +182,9 @@
 	if(size <= 0)
 		fatal("Cache_Alloc: size %d", size);
 
-	cs = mallocz(sizeof(*cs) + size, 1);
+	cs = calloc(1, sizeof(*cs) + size);
 	if(cs == nil)
-		sysfatal("Cache_Alloc: %r");
+		fatal("Cache_Alloc: %r");
 	cs->size = size;
 	cs->next = cache_head;
 	if(cache_head != nil)
--- a/zone.h
+++ b/zone.h
@@ -4,7 +4,7 @@
 }mem_user_t;
 
 #define Z_Free(p) free(p)
-#define Z_Malloc(sz) mallocz((sz), 1)
+#define Z_Malloc(sz) calloc(1, (sz))
 
 int Hunk_From(void *p);
 void Hunk_CacheFrom(mem_user_t *c, void *p);